<?xml version="1.0" encoding="UTF-8"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" ><channel><title>Nabeel Valley</title><description>Software develpment, Photography and Design</description><link>https://nabeelvalley.co.za</link><atom:link href="https://nabeelvalley.co.za/feed/rss.xml" rel="self" type="application/rss+xml" ></atom:link><item><title>Looky, a wild HTML!</title><link>https://nabeelvalley.co.za/blog/2019/12-10/looky-a-wild-html.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2019/12-10/looky-a-wild-html.html</guid><description>The first blog post, A quick journey through my design and development process for the site</description><pubDate>Sat, 12 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Looky, a wild HTML!&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Here at last&lt;/h2&gt;
&lt;p&gt;So, after far too long, we are here. A mostly-functional website, that I have not tested on a single iOS device which may prove to be problematic&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note to self, test on an iPhone or something&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the past six months or so I&amp;#39;ve looked at myself with a full stack of irony knowing that I, a web developer, do not have &lt;strong&gt;my own&lt;/strong&gt; website. Or well, not one I&amp;#39;d actually want anyone to see (*cough cough* I&amp;#39;m talking to you, Weebly)&lt;/p&gt;
&lt;h2&gt;The Design Process&lt;/h2&gt;
&lt;p&gt;Well, the design process, especially when you&amp;#39;re trying to satisfy your unattainable standard of perfection, can be difficult. I actually ran through a shocking number of iterations and end-to-end redesigns but I just could not seem to find something that satisfied me. Until one day, it all just sort of hit me at once&lt;/p&gt;
&lt;p&gt;None of this nonsensical &amp;quot;cards and shadows&amp;quot; drama, no random floopy animations, none of that, just a blank slate, with some text and imagery.&lt;/p&gt;
&lt;p&gt;I think I have a fair stock of those&lt;/p&gt;
&lt;h3&gt;Design v1&lt;/h3&gt;
&lt;p&gt;The first iteration that I have saved is this one, I had big dreams, there were going to be things moving all over the place, I was going to break the norm with &lt;strong&gt;horizontal scrolling&lt;/strong&gt;, and just basically turn the site into a slide-show. But I didn&amp;#39;t like the lack of fluidity with the overall design. Regardless, here are the first few screens:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.3333333333333333&quot; orientation=&quot;horizontal&quot; alt=&quot;design1&quot; src=&quot;/optimized-images/public/content/blog/2019/12-10/design1.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;During this initial phase I had sort figured out what my key goals were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unique experience on every device.&lt;/li&gt;
&lt;li&gt;Unobtrusive elements&lt;/li&gt;
&lt;li&gt;Clean lines&lt;/li&gt;
&lt;li&gt;I needed to take emphasis away from the design, and onto the content&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Basically, I wanted something basic&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By now I had decided on the three most important things, &lt;strong&gt;#E44D90&lt;/strong&gt;, &lt;em&gt;Montserrat&lt;/em&gt;, and &lt;code&gt;Nova Mono&lt;/code&gt;, but there&amp;#39;s still a lot I was unsure of&lt;/p&gt;
&lt;h3&gt;Design v2&lt;/h3&gt;
&lt;p&gt;This version mostly morphed out of the first one, I was trying to address two things primarily&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How can I not confuse people&lt;/li&gt;
&lt;li&gt;Actually yeah, just the first thing&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Personally, I hate this design. But It was definitely valuable in telling me what I didn&amp;#39;t want this site to be&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.3333333333333333&quot; orientation=&quot;horizontal&quot; alt=&quot;design2&quot; src=&quot;/optimized-images/public/content/blog/2019/12-10/design2.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve always disliked cards, and abusing it the way I was in that further deepened my hate. I felt kind of like &lt;em&gt;&amp;quot;Well if everyone else does it, maybe I should give it a shot?&amp;quot;&lt;/em&gt;, to be fair it&amp;#39;s probably not the cards, it&amp;#39;s me&lt;/p&gt;
&lt;h3&gt;Design v3&lt;/h3&gt;
&lt;p&gt;This is what you&amp;#39;re seeing now (Assuming you&amp;#39;re reading this in October 2019) I love how this design places a strong emphasis on the imagery and text, there isn&amp;#39;t really much else in the way of it aside from occasional underline. Simplicity&lt;/p&gt;
&lt;p&gt;I addressed my remaining goals by sticking to a basic site layout with a fairly aggressive grid to deliver interesting layouts for different devices&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.3333333333333333&quot; orientation=&quot;horizontal&quot; alt=&quot;design3&quot; src=&quot;/optimized-images/public/content/blog/2019/12-10/design3.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;That being said, and my heart being content. It was time to code&lt;/p&gt;
&lt;h2&gt;The &lt;em&gt;&amp;quot;Bashing your head against a wall&amp;quot;&lt;/em&gt; Process&lt;/h2&gt;
&lt;p&gt;I used React - Why? Because I used React. Sure, I could have went the Server-Side route and made sure I was sending normal HTML to people, but I wanted a sustainable component library that I could develop as well as super-quick responsiveness on the client, and from experience, I knew I could knock this out fastest with React. That being said, I kind of wish I had looked at setting up pre-rendering before I started, because I feel like it&amp;#39;s going to be admin to add after (will basically need to refactor out all the &lt;code&gt;&amp;lt;Suspense/&amp;gt;&lt;/code&gt;) tags&lt;/p&gt;
&lt;p&gt;Now, as any front-end developer should know in 2019, you gotta start with &lt;code&gt;npx create-react-app my-app&lt;/code&gt; and after about three years of &lt;code&gt;node_modules&lt;/code&gt; you&amp;#39;re ready to go&lt;/p&gt;
&lt;h3&gt;Content Management System?&lt;/h3&gt;
&lt;p&gt;I&amp;#39;m not going to go into the details of the development because there isn&amp;#39;t really anything too fancy going on here - the site is mostly static anyway. I will however just talk about the Content Management System&lt;/p&gt;
&lt;p&gt;Well ..., I think it depends on your view of a CMS. I really didn&amp;#39;t want to go overkill on this so I&amp;#39;m making use of a fairly simple system. Each post consists of a &lt;code&gt;post.md&lt;/code&gt; and a &lt;code&gt;post.json&lt;/code&gt; file&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;.md&lt;/code&gt; file is the Markdown file, it&amp;#39;s the file that I write in as I write the post, and potentially every post in future&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;.json&lt;/code&gt; file is also very simple at the moment and contains some &lt;code&gt;metadata&lt;/code&gt; for the post such as the title and the date. I made this separation so that I would not have to get funky with my file processing, and I&amp;#39;m fairly happy with it&lt;/p&gt;
&lt;p&gt;To process and render the Markdown I&amp;#39;m using a library that I fell in love with just over a year ago called &lt;a href=&quot;https://github.com/showdownjs/showdown&quot; &gt;&lt;code&gt;Showdown.js&lt;/code&gt;&lt;/a&gt;, and to add syntax highlighting I&amp;#39;m using some flavour of &lt;a href=&quot;https://highlightjs.org/&quot; &gt;&lt;code&gt;Highlight.js&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve then simply rendered the content by &lt;code&gt;fetch&lt;/code&gt;ing it from the &lt;em&gt;Folder-cms&lt;/em&gt; and passing it through a Markdown Component&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Converter } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;showdown&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; showdownHighlighter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;showdown-highlight&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./Markdown.css&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertMarkdownToHtml&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; converter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Converter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    headerLevelStart: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    parseImgDimensions: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    extensions: [showdownHighlighter],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; html&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; converter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;makeHtml&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Markdown&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Markdown&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    dangerouslySetInnerHTML&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{ __html: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;convertMarkdownToHtml&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(text) }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Markdown&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And that&amp;#39;s pretty much it. It gets rendered into the page you&amp;#39;re looking at now and that&amp;#39;s all it takes really. It&amp;#39;s a bit of a shame that my syntax highlighting CSS theme doesn&amp;#39;t really do justice on JS, another TODO I suppose&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There were a couple of new things I learnt during this entire process, simple little things really like how to change the colour of the scrolly thing on your browser, or how to put together a mildly-reasonable file system to store the posts, but more than anything I enjoyed being able to just take something from pure concept to a final build that lines up pretty well with my initial vision&lt;/p&gt;
&lt;p&gt;That&amp;#39;s all for now, stay tuned, lots more to come. But in the mean time take a look around, let me know what bugs you find (as I said, very untested)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Real-time Communication with MQTT</title><link>https://nabeelvalley.co.za/blog/2019/12-11/rtc-with-mqtt.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2019/12-11/rtc-with-mqtt.html</guid><description>MQTT and real-time communication with the browser, JavaScript, Web Sockets and a Mosquitto message broker</description><pubDate>Tue, 12 Nov 2019 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Real-time Communication with MQTT&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;MQTT is an open standard for communication and is especially useful for communication between IoT devices due to its low bandwidth requirements&lt;/p&gt;
&lt;p&gt;Today we&amp;#39;re going to be taking a look at using MQTT to easily communicate between multiple applications. We&amp;#39;ll look at using a static website and Eclipse Mosquitto as a message broker to enable communication between two instances of the application, but the same principles can be extended to other programming languages and MQTT clients. For our clients we&amp;#39;ll be using &lt;code&gt;MQTT.js&lt;/code&gt; which runs in the browser via CDN and we interact with it using JavaScript, but can also be added from &lt;code&gt;npm&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to follow along with the completed code you can get it &lt;a href=&quot;https://github.com/nabeelvalley/RTCWithMQTT&quot; target=&quot;_blank&quot; &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Broker&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Eclipse Mosquitto is an open-source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers. (&lt;a href=&quot;https://mosquitto.org/&quot; target=&quot;_blank&quot; &gt;Eclipse Mosquitto&lt;/a&gt; )&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Message brokers are a method of intra-application communication, MQTT makes use of a publish/subscribe model for application communication. In this model different applications, or clients, can publish messages to a topic which can then be picked up and operated on by any other applications that are subscribed to the topic&lt;/p&gt;
&lt;h3&gt;Setting Up the Broker&lt;/h3&gt;
&lt;p&gt;You will first need to download Mosquitto from &lt;a href=&quot;https://mosquitto.org/download/&quot; target=&quot;_blank&quot; &gt;here&lt;/a&gt; , all &lt;code&gt;1.5mb&lt;/code&gt; of it, and run through the installer and then ensure that &lt;code&gt;mosquitto&lt;/code&gt; is in your path. If you need to know how to add something to your path take a look at &lt;a href=&quot;https://gist.github.com/nex3/c395b2f8fd4b02068be37c961301caa7&quot; target=&quot;_blank&quot; &gt;this Gist&lt;/a&gt; . For a Windows 64 bit installation of Mosquitto you should add the following to your path &lt;code&gt;C:\Program Files\mosquitto&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The MQTT installation should include the following three commands&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;mosquitto&lt;/code&gt; - This runs the MQTT server/broker&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mosquitto_pub&lt;/code&gt; - A simple message publisher&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mosquitto_sub&lt;/code&gt; - A simple message subscriber&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can get more information by running either of the above commands with the &lt;code&gt;--help&lt;/code&gt; flag, e.g. &lt;code&gt;mosquitto --help&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Basic Messaging&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Let&amp;#39;s start the message broker in verbose mode by opening a new shell and running the &lt;code&gt;mosquitto -v&lt;/code&gt; command, you should see some output like the following:&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494107: mosquitto version 1.6.7 starting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494107: Using default config.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494107: Opening ipv6 listen socket on port 1883.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494107: Opening ipv4 listen socket on port 1883.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can see from the above that the message broker is running on our local port &lt;code&gt;1883&lt;/code&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot; &gt;
&lt;li&gt;In a new shell, we can create a client which is subscribed to a topic. We&amp;#39;ll name this topic &lt;code&gt;messages&lt;/code&gt; but it can be pretty much anything you want, to start the subscriber client we can run &lt;code&gt;mosquitto_sub -t &amp;quot;messages&amp;quot; -v&lt;/code&gt;, you won&amp;#39;t see any output in the subscriber shell as yet, but looking at the broker shell you should logging which says that a client was connected&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: New connection from ::1 on port 1883.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: New client connected from ::1 as mosq-fwbsJxdXOnQW0LOaIn (p2, c1, k60).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: No will message specified.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: Sending CONNACK to mosq-fwbsJxdXOnQW0LOaIn (0, 0)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: Received SUBSCRIBE from mosq-fwbsJxdXOnQW0LOaIn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642:     messages (QoS 0)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: mosq-fwbsJxdXOnQW0LOaIn 0 messages&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494642: Sending SUBACK to mosq-fwbsJxdXOnQW0LOaIn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494702: Received PINGREQ from mosq-fwbsJxdXOnQW0LOaIn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494702: Sending PINGRESP to mosq-fwbsJxdXOnQW0LOaIn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol start=&quot;3&quot; &gt;
&lt;li&gt;To publish a message open another shell and run &lt;code&gt;mosquitto_pub -t &amp;quot;messages&amp;quot; -m &amp;quot;This is my message!&amp;quot;&lt;/code&gt;, in our subscriber shell we should see the following output:&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;messages This is my message!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And in the broker we&amp;#39;ll see the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: New connection from ::1 on port 1883.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: New client connected from ::1 as mosq-MWbaa2TpZGV0FrTmcF (p2, c1, k60).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: No will message specified.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: Sending CONNACK to mosq-MWbaa2TpZGV0FrTmcF (0, 0)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: Received PUBLISH from mosq-MWbaa2TpZGV0FrTmcF (d0, q0, r0, m0, &amp;#39;messages&amp;#39;, ... (19 bytes))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: Sending PUBLISH to mosq-fwbsJxdXOnQW0LOaIn (d0, q0, r0, m0, &amp;#39;messages&amp;#39;, ... (19 bytes))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: Received DISCONNECT from mosq-MWbaa2TpZGV0FrTmcF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573494844: Client mosq-MWbaa2TpZGV0FrTmcF disconnected.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;When you&amp;#39;re done with this you can close the open shell windows&lt;/p&gt;
&lt;h3&gt;Broker with WebSockets&lt;/h3&gt;
&lt;p&gt;For our usecase, we will make use of WebSockets so we can communicate directly from the browser. When starting up the message broker we have the option to pass in a configuration file. Let&amp;#39;s create one that states the port and the protocol we would like to use. Create a new directory called &lt;code&gt;mqtt&lt;/code&gt;, and in it create a new file called &lt;code&gt;mosquitto.conf&lt;/code&gt; and place the following contents which simply tell it to listen on port &lt;code&gt;9001&lt;/code&gt; and use the &lt;code&gt;websockets&lt;/code&gt; protocol&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mosquitto.conf&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;listener 9001&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;protocol websockets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If you&amp;#39;d like to know what else can be done in the configuration file you can &lt;a href=&quot;https://mosquitto.org/man/mosquitto-conf-5.html&quot; target=&quot;_blank&quot; &gt;read the documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We can start the broker again from the &lt;code&gt;mqtt&lt;/code&gt; directory using &lt;code&gt;mosquitto -c mosquitto.conf -v&lt;/code&gt;, this time we should see that it is running on &lt;code&gt;9001&lt;/code&gt; with &lt;code&gt;websockets&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573499281: mosquitto version 1.6.7 starting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573499281: Config loaded from mosquitto.conf.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573499281: Opening websockets listen socket on port 9001.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we have configured the broker to use Web Sockets we can start connecting to it from a web page and publish some messages&lt;/p&gt;
&lt;h2&gt;Client&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ll be using &lt;a href=&quot;https://github.com/mqttjs/MQTT.js&quot; target=&quot;_blank&quot; &gt;MQTT.js&lt;/a&gt; to connect to our message broker. MQTT.js is a simple MQTT Client Library for connecting to message brokers, we&amp;#39;ll be using it via CDN for the sake of simplicity and will also be using &lt;a href=&quot;https://materializecss.com/&quot; target=&quot;_blank&quot; &gt;Materialize&lt;/a&gt; for our CSS because I&amp;#39;m not going to write a bunch of CSS and I don&amp;#39;t want this to look completely terrible&lt;/p&gt;
&lt;h3&gt;HTML&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s first setup the &lt;code&gt;index.html&lt;/code&gt;. It consists of a two-column layout with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Main Heading with a badge to indicate if we successfully connected to the broker&lt;/li&gt;
&lt;li&gt;Inputs to Publish Message&lt;/li&gt;
&lt;li&gt;Table of all received messages&lt;/li&gt;
&lt;li&gt;Materialize and MQTT.js files via CDN&lt;/li&gt;
&lt;li&gt;Script tag for all our JavaScript, because we don&amp;#39;t need two files for this&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; html&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;html&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; lang&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; charset&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;viewport&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; http-equiv&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;X-UA-Compatible&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;ie=edge&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Real-time Communication with MQTT&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- MQTT.js --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://unpkg.com/mqtt@3.0.0/dist/mqtt.min.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- Materialize --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- Compiled and minified CSS --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      rel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      href&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;body&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      &amp;lt;!-- Page Content goes here --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;row&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;col s12&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            Messages&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;span&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;              id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;connect-badge&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;              class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;new badge orange&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;              data-badge-caption&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;              &amp;gt;connecting&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;span&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;row&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;col s12 m6&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Input&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;input-field&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;input&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;validate&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;label&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;First Name&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;label&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;input-field&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;textarea&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;              id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;              class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;materialize-textarea&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;              data-length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;120&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;textarea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;label&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Message&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;label&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;waves-effect waves-light btn&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; onclick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;handleSubmit&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;()&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            Publish Message&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;col s12 m6&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Output&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;thead&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;              &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;tr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;th&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Name&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;th&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;th&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Message&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;th&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;              &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;tr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;thead&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;tbody&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;messages&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;tbody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // Our Javascript will go here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;body&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  &amp;lt;!-- Materialize --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  &amp;lt;!-- Compiled and minified JavaScript --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;html&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Running the Website&lt;/h3&gt;
&lt;p&gt;Since we are including resources from other domains your browser may have some issues with you using the &amp;#39;double click&amp;#39; method of running the files, so we&amp;#39;re going to need to use a web server&lt;/p&gt;
&lt;p&gt;A list of quick one-line web servers can be found on this &lt;a href=&quot;https://gist.github.com/willurd/5720255&quot; target=&quot;_blank&quot; &gt;Gist&lt;/a&gt; and if you&amp;#39;re using Visual Studio Code you can use the Live Server Extension&lt;/p&gt;
&lt;h3&gt;Connecting to the Message Broker&lt;/h3&gt;
&lt;p&gt;Now that we&amp;#39;re up and running we can connect to the broker that we set up previously. The Mosquitto Broker should be running on &lt;code&gt;127.0.0.1:9001&lt;/code&gt;, using the &lt;code&gt;mqtt&lt;/code&gt; object that is exposed in the global space by &lt;code&gt;MQTT.js&lt;/code&gt; we can simply create an instance of the client in our &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; section with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; client&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; mqtt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;connect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;mqtt://127.0.0.1:9001&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This gives us a &lt;code&gt;client&lt;/code&gt; object that is the MQTT Client connected to our broker. Next, we need to set a handler for the &lt;code&gt;connect&lt;/code&gt; event which is when the client successfully connects to the message broker, we do this with the following code:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;connect&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;subscribe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;messages&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;err&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; badge&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;connect-badge&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      badge.innerText &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;connected&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      badge.classList.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;remove&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      badge.classList.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;add&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;green&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can see that the &lt;code&gt;client.on&lt;/code&gt; function takes a callback, in which we tell our client to subscribe to the &lt;code&gt;messages&lt;/code&gt; topic as we did previously via the &lt;code&gt;mosquitto_sub&lt;/code&gt;, and then once it has successfully subscribed we change the badge status to indicate that we are connected&lt;/p&gt;
&lt;p&gt;Since we have successfully subscribed the client to the broker we should be able to publish messages. We&amp;#39;ll do that using the data from the input fields in on the page and the &lt;code&gt;Publish Message&lt;/code&gt; button&amp;#39;s handler&lt;/p&gt;
&lt;h3&gt;Publishing Messages&lt;/h3&gt;
&lt;p&gt;Create a handler for the &lt;code&gt;Publish Message&lt;/code&gt; button called &lt;code&gt;handleSubmit&lt;/code&gt;, we&amp;#39;ve already referenced this in our button&amp;#39;s HTML. The handler simply needs to read the values from the input fields and call &lt;code&gt;client.publish&lt;/code&gt; with a stringified form of the data&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handleSubmit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nameInput&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; messageInput&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    name: nameInput.value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    message: messageInput.value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; payload&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;publish&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;messages&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, payload)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;client.publish&lt;/code&gt; function above takes in a &lt;code&gt;topic&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt; as its inputs, in our case we want to publish to the &lt;code&gt;messages&lt;/code&gt; topic and we are publishing the JSON object as a string&lt;/p&gt;
&lt;p&gt;Refreshing the page, entering some text into the fields and clicking the &lt;code&gt;Publish Message&lt;/code&gt; button should publish the message to the broker, we should see this in the message broker&amp;#39;s output&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573506416: Received PUBLISH from mqttjs_d5cdbc8e (d0, q0, r0, m0, &amp;#39;messages&amp;#39;, ... (34 bytes))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1573506416: Sending PUBLISH to mqttjs_d5cdbc8e (d0, q0, r0, m0, &amp;#39;messages&amp;#39;, ... (34 bytes))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we can publish messages to the topic, we will need to create a handler for the &lt;code&gt;message&lt;/code&gt; event which is triggered every time one of our subscribed topics has something published to it. We can do this again with the &lt;code&gt;client.on&lt;/code&gt; function:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;topic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;messages&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).innerHTML &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;${&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    data&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  }&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&amp;lt;br&amp;gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Our message handler receives the &lt;code&gt;topic&lt;/code&gt;, which in our case will always be &lt;code&gt;messages&lt;/code&gt; and the &lt;code&gt;message&lt;/code&gt; which is a buffer of the data published to the topic, this will be the same data that we published using the &lt;code&gt;client.publish&lt;/code&gt; function, this time we read the JSON back into an object and add it to the messages table as HTML&lt;/p&gt;
&lt;p&gt;You should be able to open a few different windows of the web page and they should all be able to Publish Messages to one another&lt;/p&gt;
&lt;h2&gt;What Next?&lt;/h2&gt;
&lt;p&gt;If you&amp;#39;re not familiar with message brokers this could be a lot to take in and that&amp;#39;s okay. I think playing around with the &lt;code&gt;mosquitto_pub&lt;/code&gt; and &lt;code&gt;mosquitto_sub&lt;/code&gt; tools can be helpful to get a more interactive feel for the way everything works. You can also just play with the MQTT.js code we used via your browser console and looking at the documentation on the website&lt;/p&gt;
&lt;p&gt;If you want to take a look at a free instance of an MQTT Broker that you can play around with take a look at &lt;a href=&quot;https://www.cloudmqtt.com/&quot; target=&quot;_blank&quot; &gt;Cloud MQTT&lt;/a&gt; , and if you want to look at how you can take the concepts covered here today and play around with some IoT concepts as well then it may also be worth taking a look at this &lt;a href=&quot;https://developer.ibm.com/tutorials/iot-mobile-phone-iot-device-bluemix-apps-trs/&quot; target=&quot;_blank&quot; &gt;IBM Developer Tutorial&lt;/a&gt; using IBM Cloud and Watson IoT&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re interested in spinning up your own MQTT broker with custom functionality you can take a look at &lt;a href=&quot;http://www.mosca.io/&quot; &gt;Mosca&lt;/a&gt; or get an even deeper understanding of the MQTT Protocol &lt;a href=&quot;https://developer.ibm.com/articles/iot-mqtt-why-good-for-iot/&quot; target=&quot;_blank&quot; &gt;on IBM Developer&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve used a couple of different technologies and depending on your background you may not be familiar with everything here. The best thing I&amp;#39;d say to get to understand what we&amp;#39;ve covered would be to play around with the code as well as look at some of the other services and use-cases for message brokers and get a feel for what&amp;#39;s out there&lt;/p&gt;
&lt;p&gt;Good luck&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Intro to F# Web APIs</title><link>https://nabeelvalley.co.za/blog/2019/30-10/fsharp-webapi.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2019/30-10/fsharp-webapi.html</guid><description>Introduction to .NET Core Web APIs with F#</description><pubDate>Wed, 30 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Intro to F# Web APIs&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;So we&amp;#39;re going to be taking a bit of a look on how you can go about building your first F# Web API using .NET Core. I&amp;#39;m going to cover a lot of the basics, a lot of which should be familiar to anyone who has worked with .NET Web Applications and F# in general.&lt;/p&gt;
&lt;p&gt;Along the way I&amp;#39;m also going to go through some important concepts that I feel are maybe not that clear from a documentation perspective that are actually super relevant to using this F# in a real-life context&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you&amp;#39;re totally new to F# though you may want to take a look at &lt;a href=&quot;https://fsharpforfunandprofit.com/&quot; target=&quot;_blank&quot; &gt;F# for Fun and Profit&lt;/a&gt; or my personal quick reference documentation over &lt;a href=&quot;/docs/dotnet/intro-to-fs&quot; &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Assuming you&amp;#39;ve got the .NET Core SDK with F# installed, you can simply create a new project with the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;dotnet new webapi --language F# --name FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;code .\FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Alternatively, if you&amp;#39;re feeling a little &lt;em&gt;unexperimental&lt;/em&gt; you can use the Visual Studio project creation wizard, psshhtt&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once you have the project open you can run the following command to launch the application:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;dotnet run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which should start the application on &lt;code&gt;https://localhost:5001&lt;/code&gt; and &lt;code&gt;http://localhost:5000&lt;/code&gt;, you can see the current existing endpoint at &lt;code&gt;/weatherforecast&lt;/code&gt;, this is handled by the &lt;code&gt;Controllers/WeatherForecastController.fs&lt;/code&gt; file&lt;/p&gt;
&lt;h2&gt;Looking Around&lt;/h2&gt;
&lt;p&gt;Looking at the structure of the project files you should see the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│   appsettings.Development.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│   appsettings.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│   FSharpWebApi.fsproj&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│   Program.fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│   Startup.fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│   WeatherForecast.fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;├───Controllers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│       WeatherForecastController.fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;└───Properties&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;        launchSettings.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So, mostly we see the typical Web API stuff that we&amp;#39;d expect for a C# project such as the &lt;code&gt;startup&lt;/code&gt; and &lt;code&gt;program&lt;/code&gt; files. In F# they serve pretty much the same purpose.&lt;/p&gt;
&lt;p&gt;Looking at the &lt;code&gt;Program.fs&lt;/code&gt; file we can see that it contains the &lt;code&gt;main&lt;/code&gt; function and configures the Web Host, next we can see that the &lt;code&gt;Startup.fs&lt;/code&gt; file contains the usual configuration methods. We should note that the method calls within these functions are piped to an &lt;code&gt;ignore&lt;/code&gt; so the the functions to not return their respective &lt;code&gt;Builders&lt;/code&gt; as this will break the application&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Program.fs&lt;/code&gt; and &lt;code&gt;Startup.fs&lt;/code&gt; files can be seen below&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Program.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;module&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Program &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; exitCode&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CreateHostBuilder args &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        Host.CreateDefaultBuilder&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            .ConfigureWebHostDefaults&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(fun&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; webBuilder &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                webBuilder.UseStartup&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Startup&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    [&amp;lt;EntryPoint&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; main args &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        CreateHostBuilder&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.Build&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.Run&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        exitCode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;Startup.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Startup&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    new&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;configuration&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IConfiguration&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        Startup&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        this.Configuration &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; configuration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // This method gets called by the runtime. Use this method to add services to the container.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; this.ConfigureServices&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;services&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IServiceCollection&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        // Add framework services.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        services.AddControllers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; this.Configure&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;app&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IApplicationBuilder&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; env&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IWebHostEnvironment&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;env.IsDevelopment&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;())&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            app.UseDeveloperExceptionPage&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        app.UseHttpsRedirection&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        app.UseRouting&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        app.UseAuthorization&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        app.UseEndpoints&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(fun&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; endpoints &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            endpoints.MapControllers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            )&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    member val&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Configuration &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IConfiguration &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; set&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next we have the &lt;code&gt;FSharpWebApi.fsproj&lt;/code&gt; file which contains references to the relevant code files. It&amp;#39;s important to note that the order of the files in the &lt;code&gt;ItemGroup&lt;/code&gt; specifies the order that files depend on each other. Lower files depend on files higher up&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;xml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Project&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Sdk&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Microsoft.NET.Sdk.Web&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;PropertyGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;TargetFramework&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;netcoreapp3.0&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;TargetFramework&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;PropertyGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;WeatherForecast.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Controllers/WeatherForecastController.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Startup.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Program.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Project&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Lastly, we have a controller that resides in the &lt;code&gt;Controllers/WeatherForecastController.fs&lt;/code&gt; with its types defined in the &lt;code&gt;WeatherForecast.fs&lt;/code&gt; file. Looking at the &lt;code&gt;WeatherForecast.fs&lt;/code&gt; file we can see that the type has a few simple properties and one function&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WeatherForecast.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; System&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WeatherForecast&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Date&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DateTime&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      TemperatureC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Summary&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; string &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; this.TemperatureF&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        32&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;int &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;float this.TemperatureC &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0.5556&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next up, we can see the controller which contains a single &lt;code&gt;GET&lt;/code&gt; endpoint which delivers a random array of weather forecasts. Here we can see a few different things. First, the namespace is &lt;code&gt;FSharpWebApi.Controllers&lt;/code&gt;, this pretty much follows the .NET standard of the Namespace being related to the Folder name, we can also see the &lt;code&gt;ApiController&lt;/code&gt; attribute that adds &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.0#apicontroller-attribute&quot; target=&quot;_blank&quot; &gt;some useful functionality&lt;/a&gt; for basic API handling and the &lt;code&gt;Route&lt;/code&gt; attribute that states the controller route&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;WeatherForecastController&lt;/code&gt; type defines the controller and that it inherits from &lt;code&gt;ControllerBase&lt;/code&gt;, additionally the constructor requires the &lt;code&gt;ILogger&lt;/code&gt; service which will be provided by DependencyInjection&lt;/p&gt;
&lt;p&gt;Lastly, looking at the &lt;code&gt;__Get&lt;/code&gt; method we can see the &lt;code&gt;HttpGet&lt;/code&gt; attribute that specifies that this is a Get Method, and the &lt;code&gt;__&lt;/code&gt; shows that we don&amp;#39;t care about references to the function&amp;#39;s &lt;code&gt;this&lt;/code&gt;, and the return type for the function is an &lt;code&gt;array&lt;/code&gt; of &lt;code&gt;WeatherForecast&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WeatherForecastController.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharpWebApi.Controllers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; System&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Microsoft.Extensions.Logging&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharpWebApi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;ApiController&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;Route&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;[controller]&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WeatherForecastController&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;logger &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ILogger&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;WeatherForecastController&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    inherit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ControllerBase&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; summaries&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; [|&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Freezing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Bracing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Chilly&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Cool&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Mild&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Warm&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Balmy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hot&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Sweltering&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Scorching&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    [&amp;lt;HttpGet&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; __.Get&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WeatherForecast&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;[]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; rng&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; System.Random&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        [|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; index &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;in&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;                {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Date &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DateTime.Now.AddDays&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;float index&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                  TemperatureC &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; rng.Next&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;55&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                  Summary &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; summaries&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.[&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;rng.Next&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;summaries.Length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Creating a Controller&lt;/h2&gt;
&lt;p&gt;Creating a new controller is not particularly complex given that we have the above as a starting point.&lt;/p&gt;
&lt;h2&gt;Get Handler&lt;/h2&gt;
&lt;p&gt;We&amp;#39;re going to create a handler that is able to return a simple message for an &lt;code&gt;even&lt;/code&gt; param, and a &lt;code&gt;404&lt;/code&gt; for a &lt;code&gt;odd&lt;/code&gt; param in order to look at how we can return actual response codes in cases where we aren&amp;#39;t always able to return something of a constant type&lt;/p&gt;
&lt;p&gt;First, we can create a &lt;code&gt;Controllers/MessageController.fs&lt;/code&gt; file with just some basic scaffolding to start with. We&amp;#39;ll define a &lt;code&gt;Get&lt;/code&gt; controller that just returns the &lt;code&gt;id&lt;/code&gt; it receives as a route param multiplied by two if the the result &lt;code&gt;shouldDouble&lt;/code&gt; param is set to &lt;code&gt;true&lt;/code&gt;. Additionally we can see the &lt;code&gt;sprint&lt;/code&gt; function used to format the output as a string&lt;/p&gt;
&lt;p&gt;Before we can add the data to the actual controller we need to add the &lt;code&gt;&amp;lt;Compile Include=&amp;quot;Controllers/MessageController.fs&amp;quot; /&amp;gt;&lt;/code&gt; to the &lt;code&gt;ItemGroup&lt;/code&gt; in the &lt;code&gt;FSharpWebApi.fsproj&lt;/code&gt; file, :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FSharpWebApi.fsproj&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;xml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;WeatherForecast.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Controllers/WeatherForecastController.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Controllers/MessageController.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Startup.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Program.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then we can put together the controller in the &lt;code&gt;MessageController.fs&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MessageController.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharpWebApi.Controllers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Microsoft.Extensions.Logging&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;ApiController&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;Route&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;[controller]&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MessageController&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;logger &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ILogger&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;MessageController&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    inherit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ControllerBase&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    [&amp;lt;HttpGet&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;{id}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; __.Get &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; int&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; shouldDouble &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; bool&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        logger.LogInformation&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;I am a controller&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; shouldDouble &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        sprintf &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;From the function&amp;#39;s signature we can see that it has an &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;shouldDouble&lt;/code&gt; values as inputs and that it returns a string. We have made these explicit however if we were to leave them out it would be fine too as F# would be able to infer the types, see that below:&lt;/p&gt;
&lt;p&gt;We can open the following URLs in our browser and should be able to open the &lt;code&gt;/message/3&lt;/code&gt; and &lt;code&gt;/message/3?shouldDouble=true&lt;/code&gt; routes and see &lt;code&gt;hello 3&lt;/code&gt; and &lt;code&gt;hello 6&lt;/code&gt; respectively&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that if not specified the handler inputs will try to be parsed from the body&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, if we would want to update this to return some sort of general HTTP Response Code when a user sends some kind of input, for example if the &lt;code&gt;result&lt;/code&gt; is 4, we will need to modify the function such that we are able to reference the &lt;code&gt;this&lt;/code&gt; and the return type of the function is now an &lt;code&gt;IActionResult&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;HttpGet&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;{id}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; this.Get &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; int&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; shouldDouble &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; bool&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IActionResult &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    logger.LogInformation&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;I am a controller&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; shouldDouble &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.NoContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        sprintf &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.Ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;From this we can see that we are using an additional match to either return &lt;code&gt;this.NoContent()&lt;/code&gt; as an &lt;code&gt;IActionResult&lt;/code&gt; or &lt;code&gt;this.Ok&lt;/code&gt; with the piped message as an &lt;code&gt;IActionResult&lt;/code&gt;. Just note that the following matches are equivalent:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// call the `this.Ok` function with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.NoContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    this.Ok&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;sprintf &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// pipe the result of the format through&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.NoContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    sprintf &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.Ok&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// pipe the result of the format through on a single line&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.NoContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sprintf &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; this.Ok &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; IActionResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Post Handler&lt;/h2&gt;
&lt;p&gt;We can also create a &lt;code&gt;POST&lt;/code&gt; handler that will pretty much do the same as the above handler, we can pretty much just take the values from the function body and pass it to the previous handler we put together&lt;/p&gt;
&lt;p&gt;Before we can create the handler, we need to create a type called &lt;code&gt;PostData&lt;/code&gt; that can be used by the method to receive data, we can define this towards the top of the file, above the type definition for our &lt;code&gt;MessageController&lt;/code&gt;. The type also needs to have the &lt;code&gt;CLIMutable&lt;/code&gt; attribute so that the JSON deserializer can parse the data from the post body into it correctly&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;CLIMutable&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PostData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      shouldDouble &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; bool &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next we simply need to define the &lt;code&gt;Post&lt;/code&gt; method with an &lt;code&gt;HttpPost&lt;/code&gt; attribute which will just call the &lt;code&gt;this.Get&lt;/code&gt; using the input params. this can be done pretty simply too&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;HttpPost&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;member&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; this.Post&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PostData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IActionResult &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    this.Get&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data.id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.shouldDouble&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And that&amp;#39;s really all that&amp;#39;s needed&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So yeah, that&amp;#39;s pretty much it - Not that bad right? I feel like there are a couple of things that feel a little bit weird because of the pieces of OOP running around from C# that add a bit more overhead than I&amp;#39;d like, but it&amp;#39;s .NET, that&amp;#39;s inevitable&lt;/p&gt;
&lt;p&gt;Still a few more to posts on F# to come, so stay in tuned&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>The Gatsby Migration, pt.2 - Dumb Pages</title><link>https://nabeelvalley.co.za/blog/2020/01-02/gatsby-migration-2.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/01-02/gatsby-migration-2.html</guid><description>Migrating a React.js website to Gatsby.js</description><pubDate>Sat, 01 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;The Gatsby Migration, pt.2 - Dumb Pages&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In the &lt;a href=&quot;/blog/2020/21-01/gatsby-migration-1&quot; &gt;last post&lt;/a&gt; we looked setting up an application with a few basic routes. These routes were all assigned to Components in the &lt;code&gt;src/pages&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;This post will be going throught the Gatsby Setup necessary in order to migrate our current site to Gatsby, we will be looking at the second step in the process that was outlined in the last post:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2020/21-01/gatsby-migration-1&quot; &gt;Creating the initial React App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendering the &amp;quot;Dumb&amp;quot; pages with Gatsby&lt;/strong&gt; (This post)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2020/15-03/gatsby-migration-3&quot; &gt;Rendering the &amp;quot;Smart&amp;quot; page with Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Getting Ready&lt;/h2&gt;
&lt;p&gt;In order to &lt;code&gt;Gatsbyify&lt;/code&gt; the application, there are three steps that we will need to take before we can start updating our pages to work with the new system&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Update folder structure&lt;/li&gt;
&lt;li&gt;Install Gatsby&lt;/li&gt;
&lt;li&gt;Create the necessary Gatsby Config files&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Update Folder Structure&lt;/h3&gt;
&lt;p&gt;Gatsby Builds are placed into the &lt;code&gt;public&lt;/code&gt; directory. This currently is the output directory of a React build if we are using the standard React configuration&lt;/p&gt;
&lt;p&gt;Before we do anything more we should rename our &lt;code&gt;public&lt;/code&gt; directory to &lt;code&gt;static&lt;/code&gt; as this is what Gatsby uses for static files, and then make a &lt;code&gt;git commit&lt;/code&gt; before we add the &lt;code&gt;public&lt;/code&gt; directory to our &lt;code&gt;.gitignore&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now we need to add the following lines to the end of our &lt;code&gt;.gitignore&lt;/code&gt; file so that we do not track the gatsby build files:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## gatsby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;public&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;.cache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Install Gatsby&lt;/h3&gt;
&lt;p&gt;To add Gataby to our project we need to add the &lt;code&gt;gatsby&lt;/code&gt; package from &lt;code&gt;npm&lt;/code&gt; as a dependency to our project. From the project&amp;#39;s root directory run:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn add gatsby&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next we&amp;#39;ll add/update the following commands in our &lt;code&gt;package.json&lt;/code&gt; file so that we can start the Gatsby Dev Server as well as build the application&lt;/p&gt;
&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;scripts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;start&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;gatsby develop&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;build&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;gatsby build&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;clean&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;gatsby clean&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Create Config Files&lt;/h3&gt;
&lt;p&gt;In order to enable gatsby we need to add the &lt;code&gt;gatsby-config.js&lt;/code&gt; file to our root directory, we can use the starter file with the following content, as it currently stands this doesn&amp;#39;t do anything&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gatsby-config.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;module&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;exports&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  plugins: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next we&amp;#39;ll create an &lt;code&gt;html.js&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt; directory with any relevant content from your &lt;code&gt;index.html&lt;/code&gt; file if any of it has been updated. Also be sure to remove the &lt;code&gt;%PUBLIC_URL%&lt;/code&gt; stuff from the file content&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;html.js&lt;/code&gt; file needs to be a React Component with the following basic structure for a standard CRA app&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/html.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; PropTypes &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;prop-types&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; HTML&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;(props) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;html&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; {...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;props.htmlAttributes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; charSet&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; rel&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;shortcut icon&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/favicon.png&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;viewport&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;width=device-width, initial-scale=1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;theme-color&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;#ffffff&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; rel&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;manifest&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/manifest.json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;React App&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;          dangerouslySetInnerHTML&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            __html: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;                        // Any scripts that need to be included in the HTML itself&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;                        // Like tracking code, etc.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;                        console.log(&amp;quot;Inline Javascript&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;                    `&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;props.headComponents&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;body&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; {...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;props.bodyAttributes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;props.preBodyComponents&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;          key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`body`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;          id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;___gatsby&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;          dangerouslySetInnerHTML&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{ __html: props.body }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;props.postBodyComponents&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;body&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;html&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;HTML&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.propTypes &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  htmlAttributes: PropTypes.object,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  headComponents: PropTypes.array,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  bodyAttributes: PropTypes.object,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  preBodyComponents: PropTypes.array,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  body: PropTypes.string,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  postBodyComponents: PropTypes.array,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can add or remove any elements in that file as per your specific requirements but most of the time the above should be fine&lt;/p&gt;
&lt;p&gt;Now that we have updated the &lt;code&gt;index.js&lt;/code&gt; file delete the &lt;code&gt;static/index.html&lt;/code&gt; file you can run the Gatsby Dev Server&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yarn clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yarn start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Your application should now be running on &lt;code&gt;http://localhost:8000/&lt;/code&gt;, if started correctly you should see the Gatsby Development 404 Page:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Development 404 Page&lt;/summary&gt;&lt;h1&gt;Gatsby.js development 404 page&lt;/h1&gt;&lt;p&gt;There&amp;#39;s not a page yet at /&lt;/p&gt;
&lt;p&gt;&lt;button&gt;Preview custom 404 page&lt;/button&gt;&lt;/p&gt;
&lt;p&gt;Create a React.js component in your site directory at src/pages/index.js and this page will automatically refresh to show the new page component you created.&lt;/p&gt;
&lt;p&gt;If you were trying to reach another page, perhaps you can find it below.&lt;/p&gt;
&lt;h2&gt;Pages (4)&lt;/h2&gt;&lt;p&gt;Search:&lt;/p&gt;
&lt;p&gt;&lt;label&gt;Search:&lt;input type=&quot;text&quot; id=&quot;search&quot; placeholder=&quot;Search pages...&quot; value=&quot;&quot; &gt;&lt;/label&gt;&lt;input type=&quot;submit&quot; value=&quot;Submit&quot; &gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/Blog/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Home/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/NotFound/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Post/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;&lt;h2&gt;Page Setup&lt;/h2&gt;
&lt;p&gt;From the Development 404 Page we can see that Gatsby has found our previously created pages - this is because Gatsby looks for pages in the &lt;code&gt;pages&lt;/code&gt; directory, however when we click on a the links we will notice the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Home&lt;/code&gt; and &lt;code&gt;404&lt;/code&gt; render correctly&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Blog&lt;/code&gt; results in an error message&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Post&lt;/code&gt; results in an error message (we will address this page in the next post)&lt;/li&gt;
&lt;li&gt;Routes aren&amp;#39;t aligned with our initial setup&lt;/li&gt;
&lt;li&gt;Components no longer have the layout we setup in the &lt;code&gt;App.js&lt;/code&gt; file&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are, for the most part, easy problems to solve&lt;/p&gt;
&lt;h3&gt;Fix the Blog Error Message&lt;/h3&gt;
&lt;p&gt;If we look at the &lt;code&gt;Blog&lt;/code&gt; page we will see that there is an issue with the Page render, this is because we need to change the &lt;code&gt;Link&lt;/code&gt; components to be imported from &lt;code&gt;gatsby&lt;/code&gt; instead of &lt;code&gt;react-router-dom&lt;/code&gt; because with Gatsby we are no longer using the React Router&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Blog.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Link } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;gatsby&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Fix the Routes&lt;/h3&gt;
&lt;p&gt;We can also see that our routes are capitalized which is not what we want. Gatsby uses the file organization to do routing, so in order to correct our routes to align what we defined previously in our &lt;code&gt;App.js&lt;/code&gt; we will first need to rename our files:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Old Name&lt;/th&gt;
&lt;th&gt;New Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Home&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Home.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blog&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/blog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Blog.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;blog.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NotFound&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NotFound.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;404.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;We&amp;#39;re not going to handle the &lt;code&gt;Post&lt;/code&gt; component for now because this uses a dynamic route which is something I&amp;#39;ll cover in the next part of this series&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You should stop and restart the Gatsby Dev server with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;When the page loads up we should now see our &lt;code&gt;Home&lt;/code&gt; content rendered on the &lt;code&gt;/&lt;/code&gt; route&lt;/p&gt;
&lt;h3&gt;Fix the Layout&lt;/h3&gt;
&lt;p&gt;When we were using the standard React Routing we made use of the &lt;code&gt;App&lt;/code&gt; component to wrap our page routes as well as our navigation. We&amp;#39;ll convert our &lt;code&gt;App.js&lt;/code&gt; file into a component that we can use in our other pages&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remove the &lt;code&gt;Router&lt;/code&gt; and &lt;code&gt;Switch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Update the &lt;code&gt;Link&lt;/code&gt;s to use &lt;code&gt;gatsby&lt;/code&gt; instead of &lt;code&gt;react-router-dom&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;children&lt;/code&gt; input parameter&lt;/li&gt;
&lt;li&gt;Render the &lt;code&gt;children&lt;/code&gt; in the &lt;code&gt;main&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;Remove unused imports&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;App.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./App.css&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Link } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;gatsby&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; App&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;App&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;header&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;nav&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;My Website Title&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Home&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Blog&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;nav&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;header&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Use the Layout&lt;/h3&gt;
&lt;p&gt;Now that we&amp;#39;ve essentially created a &lt;code&gt;Layout&lt;/code&gt; component in the form of the &lt;code&gt;App&lt;/code&gt; component we can use it to wrap the pages that we&amp;#39;ve exported. We can do this for the &lt;code&gt;Home&lt;/code&gt; page like so:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; App &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../App&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Home&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Home&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Home&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is the Home page&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The same applies for the &lt;code&gt;blog&lt;/code&gt; and &lt;code&gt;404&lt;/code&gt; pages&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Blog&lt;/summary&gt;&lt;p&gt;&lt;code&gt;blog.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Link } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;gatsby&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; App &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../App&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Blog&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Blog&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Blog&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is the Blog page&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/post-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Post 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/post-2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Post 2&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Blog&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;details&gt;
&lt;summary&gt;404&lt;/summary&gt;&lt;p&gt;&lt;code&gt;404.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; App &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../App&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; NotFound&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;NotFound&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;404&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Page Not Found&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; NotFound&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h3&gt;Fix the CSS&lt;/h3&gt;
&lt;p&gt;Before we can use the &lt;code&gt;App&lt;/code&gt; component we need to add the &lt;code&gt;gatsby-plugin-postcss&lt;/code&gt; and &lt;code&gt;postcss-preset-env&lt;/code&gt; plugins so that Gatsby knows how to interpret the default &lt;code&gt;create-react-app&lt;/code&gt; method of importing our CSS into a component&lt;/p&gt;
&lt;p&gt;Stop the Dev Server and install the required packages:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn add gatsby-plugin-postcss postcss-preset-env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We then need to update the &lt;code&gt;gatsby-config.js&lt;/code&gt; file to use the plugin we just added:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gatsby-config.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;module&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;exports&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  plugins: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      resolve: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`gatsby-plugin-postcss`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      options: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        postCssPlugins: [&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`postcss-preset-env`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)({ stage: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; })],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If you start the application now you&amp;#39;ll notice that the font is not correct, this is because we specify the font styles in the &lt;code&gt;index.css&lt;/code&gt; file. In order to fix this we need to import the &lt;code&gt;index.css&lt;/code&gt; file into our application, in the default React application this is done via the &lt;code&gt;src/index.js&lt;/code&gt; file, but since we don&amp;#39;t use that to load up the application anymore we need to create another file to do that with Gatsby&lt;/p&gt;
&lt;p&gt;In the root directory create a file called &lt;code&gt;gatsby-browser.js&lt;/code&gt;, in this we just need to import the &lt;code&gt;index.css&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gatsby-browser.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./src/index.css&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can now run the following commands and start up the application:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Assuming everything went as planned the application should start up correctly and the styling from our &lt;code&gt;index.css&lt;/code&gt; file will be correctly applied&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;By now we have completed the first part of the migration process - converting our static pages to use Gatsby - by taking the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Updating our file structure to better align with Gatsby&lt;/li&gt;
&lt;li&gt;Create the relevant Gatsby config files&lt;/li&gt;
&lt;li&gt;Update our &lt;code&gt;Link&lt;/code&gt; usage&lt;/li&gt;
&lt;li&gt;Update our Routing&lt;/li&gt;
&lt;li&gt;Use a shared layout component&lt;/li&gt;
&lt;li&gt;Fixing the CSS to work with Gatsby&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the next part we&amp;#39;ll look at how we can go about providing the data needed for our &lt;code&gt;Post&lt;/code&gt; component using GraphQL and show our posts. We&amp;#39;ll also look at how we can pre-process the data that we provide to our component so that we can enhance our content while improving our content creation process&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Debug POSTs using an Express App</title><link>https://nabeelvalley.co.za/blog/2020/04-12/post-endpoint-logger-express.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/04-12/post-endpoint-logger-express.html</guid><description>Create an express.js app with an endpoint that logs and returns a request&#39;s JSON body</description><pubDate>Fri, 04 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Debug POSTs using an Express App&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Sometimes it&amp;#39;s useful to have an endpoint that you can use to debug data that&amp;#39;s being &lt;code&gt;POST&lt;/code&gt;ed to an application&lt;/p&gt;
&lt;p&gt;You can make use of the following &lt;code&gt;express.js&lt;/code&gt; app to log your application&amp;#39;s POST requests:&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/Express-POST-Logger?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
&lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; express&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; app&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; express&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// parse json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;app.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;use&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(express.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;json&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// GET endpoint to check uptime&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;app.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;req&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;json&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ data: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// POST endpointthat logs request body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;app.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;post&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;req&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(req.body)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;json&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(req.body)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// listen for requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; listener&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; app.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;listen&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;listening on port &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; listener.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;address&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().port)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;detail&gt;&lt;/detail&gt;&lt;/details&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Web APIs with AdonisJS and PostgreSQL</title><link>https://nabeelvalley.co.za/blog/2020/06-09/first-look-at-adonisjs.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/06-09/first-look-at-adonisjs.html</guid><description>A look at developing Web APIs using the AdonisJS Framework and MongoDB</description><pubDate>Sun, 06 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Web APIs with AdonisJS and PostgreSQL&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;In this post, we&amp;#39;ll take a look at building an API using the AdonisJS framework. We&amp;#39;ll specifically be looking at the &lt;a href=&quot;https://preview.adonisjs.com/&quot; &gt;AdonisJS v5 Release Preview&lt;/a&gt; and how we can create a simple REST API that handles some CRUD operations on a Database&lt;/p&gt;
&lt;p&gt;Because we&amp;#39;re going to be creating a REST API, you should have some experience making HTTP Requests, for our purposes we can use a website called &lt;a href=&quot;https://postwoman.io/&quot; &gt;Postwoman&lt;/a&gt; to interact with our API, but you can also use any other tool you prefer&lt;/p&gt;
&lt;h2&gt;About AdonisJS&lt;/h2&gt;
&lt;p&gt;AdonisJS is an opinionated, Typescript-first web framework that provides a lot more &amp;quot;out of the box&amp;quot; functionality than the traditional framework or library in the Node.js ecosystem and is more comparable to something like .NET&amp;#39;s WebAPI or MVC Framework than things like Express or Next in Node.js&lt;/p&gt;
&lt;p&gt;Some of the built-in features and decisions that stand out for me are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First-class Typescript support&lt;/li&gt;
&lt;li&gt;Class-based controllers&lt;/li&gt;
&lt;li&gt;Class-Based SQL ORM&lt;/li&gt;
&lt;li&gt;Dependency Injection&lt;/li&gt;
&lt;li&gt;Request Body Validation&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Server-side View Rendering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a lot more features, and it would be impractical for me to talk about all of them in a single post. Overall, the framework seems to be very complete at this point&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ll be using a Node.js and a SQL Database for this post, so if you&amp;#39;re going to follow along with this post you will need to have a couple of things installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://nodejs.org/&quot; &gt;Node.js and NPM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Any Supported SQL Database:&lt;ul&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;Microsoft SQL Server&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MariaDB&lt;/li&gt;
&lt;li&gt;OracleDB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alternatively, you can run a Docker image for the database which may be easier, I&amp;#39;ll be using Postgres via Docker with VSCode&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To learn more about VSCode Dev Containers you can look at &lt;a href=&quot;/blog/2020/25-07/developing-in-a-container-vscode/&quot; &gt;my previous post&lt;/a&gt; on how to use Dev Containers&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Initialize an Application&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve got all our necessary dependencies installed, we can initialize an application using the &lt;code&gt;npm init&lt;/code&gt; command:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;During the initialization the CLI will ask you what type of project to initialize, be sure to select &lt;code&gt;API Server&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; init&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; adonis-ts-app&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above command is made up of the following parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;npm init&lt;/code&gt; which is the npm command that will run an initialization script from the provided package&lt;/li&gt;
&lt;li&gt;&lt;code&gt;adonis-ts-app&lt;/code&gt; which is the package to be used for initialization&lt;/li&gt;
&lt;li&gt;&lt;code&gt;my-api&lt;/code&gt; is the name of the folder/project we want to create&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once the project has been configured, navigate into the project directory:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And start the app:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;The Ace CLI&lt;/h2&gt;
&lt;p&gt;AdonisJS makes use of a command-line application called &lt;code&gt;ace&lt;/code&gt;, &lt;code&gt;ace&lt;/code&gt; can be used to do common tasks as well as custom tasks that we define. By default, it can scaffold controllers, commands, and a bunch of other things as well as run and build an AdonisJS application&lt;/p&gt;
&lt;h2&gt;Environment Variables&lt;/h2&gt;
&lt;p&gt;AdonisJS Makes use of Environment Variables do set the application configuration, in your generated files you should see a file named &lt;code&gt;.env&lt;/code&gt;, this file contains the environment variables used by the application. Looking at this file will give us an idea of our current configuration:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;3333&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;HOST&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;0.0.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;development&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;APP_KEY&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;mE8zN8V_7PzazKfv9_ds-8CGjVRLA2wo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At the moment, we can see that our application will be listening on host &lt;code&gt;0.0.0.0&lt;/code&gt; and port &lt;code&gt;3333&lt;/code&gt;, this means that we can access our application from our browser at &lt;code&gt;http://localhost:3333&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If we open this page on our browser we will see the adonis logs kicked off in our command line, something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ℹ&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  info&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      cleaning&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; up&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; build&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; directory&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ℹ&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  info&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      copy&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; .env,ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;☐&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  pending&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;   compiling&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; typescript&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; source&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;✔&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  success&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;   built&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; successfully&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ℹ&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  info&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      copy&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; .adonisrc.json&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;…&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  watch&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;     watching&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; file&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; system&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; for&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ℹ&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  info&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      starting&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; http&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;✔&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  create&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    ace-manifest.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[1595755199986] INFO  (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;my-app/1531&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; on&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; 47f057d8722c&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): started server on 0.0.0.0:3333&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The first request may take some time, this is because the server is still starting itself up. In the meantime, however, let&amp;#39;s discuss how we&amp;#39;ll be accessing our API&lt;/p&gt;
&lt;h2&gt;Making Requests&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;You will need to use &lt;a href=&quot;https://postwoman.io/&quot; &gt;Postwoman&lt;/a&gt; or something similar when making requests&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now that our application is running, we can start making requests to our API. By default, AdonisJS sets up a &lt;code&gt;hello-world&lt;/code&gt; route at the base of our application (the &lt;code&gt;/&lt;/code&gt; route`)&lt;/p&gt;
&lt;p&gt;We can reach this endpoint by simply making a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;http://localhost:3333&lt;/code&gt; which will return the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;AdonisJS can define routes using a method similar to libraries like Express.js, the &amp;quot;Hello World&amp;quot; route is defined in the &lt;code&gt;start/routes.ts&lt;/code&gt; file and has the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;routes.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Route &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@ioc:Adonis/Core/Route&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Route.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { hello: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;world&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;Route.get&lt;/code&gt; portion states that this is a &lt;code&gt;GET&lt;/code&gt; route on the &lt;code&gt;/&lt;/code&gt; path with an &lt;code&gt;async&lt;/code&gt; handler function that returns an object&lt;/p&gt;
&lt;p&gt;However, for this post, we won&amp;#39;t be defining our route&amp;#39;s handler functions like this. We&amp;#39;re going to make use of &lt;code&gt;controllers&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Controllers&lt;/h2&gt;
&lt;p&gt;AdonisJS uses &lt;code&gt;controllers&lt;/code&gt; to structure our API. This makes use of a &lt;code&gt;class&lt;/code&gt; which contains functions intended to work as an interface between the HTTP request and the work we want to do via a &lt;code&gt;provider&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We will simply state which &lt;code&gt;controller&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt; we want to use in our &lt;code&gt;routes.ts&lt;/code&gt; file instead of containing all the handler logic in that file&lt;/p&gt;
&lt;p&gt;To generate a controller we can use &lt;code&gt;ace&lt;/code&gt;. We will use &lt;code&gt;ace&lt;/code&gt; to create a &lt;code&gt;UsersContoller&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, stop your running application with &lt;code&gt;ctrl + c&lt;/code&gt; in the terminal, then use the following &lt;code&gt;ace&lt;/code&gt; command to generate a &lt;code&gt;User&lt;/code&gt; &lt;code&gt;controller&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; make:controller&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; User&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will generate an &lt;code&gt;app/Controllers/Http/UsersController.ts&lt;/code&gt; file with the following contents:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UsersController.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UsersController {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which exports a class called &lt;code&gt;UsersController&lt;/code&gt; with no default functionality&lt;/p&gt;
&lt;p&gt;We can create any functions inside of here that we want to, and then map these functions to routes. For now, let&amp;#39;s add a &lt;code&gt;get&lt;/code&gt; function that will put some placeholder data into. We&amp;#39;ll update this later to use our database&lt;/p&gt;
&lt;p&gt;A few things to note about the function we&amp;#39;re going to create:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The function is asynchronous, so if there are any long-running operations it won&amp;#39;t block other things from running&lt;/li&gt;
&lt;li&gt;The name of the function is &lt;code&gt;get&lt;/code&gt; and it has no parameters&lt;/li&gt;
&lt;li&gt;The function returns an array of objects that represents a &lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;UsersController.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UsersController {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        id: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Bob Smith&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        email: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;bob@smithmail.com&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we have defined our function, we can add a &lt;code&gt;route&lt;/code&gt; that will cause this function to be called. We do this by adding the following in the &lt;code&gt;routes.ts&lt;/code&gt; file:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Route.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;users&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;UsersController.get&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then run &lt;code&gt;npm start&lt;/code&gt; from the command line and make a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;http://localhost:3333/users&lt;/code&gt; which should return our user:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Bob Smith&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;email&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob@smithmail.com&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Database&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve got some basic understanding of how AdonisJS maps routes to functionality, we can connect our application to a Database&lt;/p&gt;
&lt;p&gt;To add database functionality, we first want to install the &lt;code&gt;adonisjs/lucid&lt;/code&gt; package to our application. Behind the scenes, AdonisJS makes use of &lt;code&gt;Lucid&lt;/code&gt; for connecting to and working with databases&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; i&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; @adonisjs/lucid@alpha&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then run the following command to initialize it:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; invoke&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; @adonisjs/lucid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which should give the following output:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;   create    config/database.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;   update    .env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;   update    tsconfig.json { types += @adonisjs/lucid }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;   update    .adonisrc.json { commands += @adonisjs/lucid/build/commands }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;   update    .adonisrc.json { providers += @adonisjs/lucid }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;✔  create    ace-manifest.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If you open your &lt;code&gt;.env&lt;/code&gt; file you will see the configuration for a &lt;code&gt;sqlite&lt;/code&gt; database&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## ... other config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_CONNECTION&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;sqlite&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;127.0.0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_USER&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;lucid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_PASSWORD&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;lucid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_NAME&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;lucid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can follow the general database setup information on the &lt;a href=&quot;https://preview.adonisjs.com/guides/database/setup&quot; &gt;AdonisJS Docs&lt;/a&gt; to set yours up, but I&amp;#39;ll be using Postgres as I&amp;#39;ve mentioned before&lt;/p&gt;
&lt;p&gt;To use Postgress, you need to install the &lt;code&gt;pg&lt;/code&gt; package from npm:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; i&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; pg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then configure your application to use Postgres. We will first update our &lt;code&gt;.env&lt;/code&gt; file to have our database credentials:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_CONNECTION&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;pg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_USER&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_PASSWORD&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;pass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_NAME&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;DB_PORT&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;5432&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once you&amp;#39;ve configured your database connection information in the &lt;code&gt;.env&lt;/code&gt; file, our database connection information will be taken care of by AdonisJS&lt;/p&gt;
&lt;p&gt;These environment variables are used in the &lt;code&gt;config/database.ts&lt;/code&gt; file, we can see them in the &lt;code&gt;pg&lt;/code&gt; part of the file&lt;/p&gt;
&lt;p&gt;&lt;code&gt;database.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    pg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      client&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;pg&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      connection&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        host&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Env.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;DB_HOST&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        port&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Env.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;DB_PORT&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5432&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        user&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Env.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;DB_USER&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lucid&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        password&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Env.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;DB_PASSWORD&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lucid&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        database&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Env.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;DB_NAME&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lucid&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      healthCheck&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the &lt;code&gt;database.ts&lt;/code&gt; file above, look for the section for your relevant database, and set the &lt;code&gt;healthCheck&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve set things up, we can create a health-check route that will enable us to view the current status of our database connection. We will add a handler for this in the &lt;code&gt;routes.ts&lt;/code&gt; file:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; HealthCheck &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@ioc:Adonis/Core/HealthCheck&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ... existing file content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Route.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;health&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;response&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; report&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; HealthCheck.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getReport&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; report.healthy &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; response.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(report) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; response.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;badRequest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(report)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once you&amp;#39;ve done all the above, start the development server again with &lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then make a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;http://localhost:3333/health&lt;/code&gt; to view your health-check information&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;healthy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;report&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;env&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;displayName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Node Env Check&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;health&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        &amp;quot;healthy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;appKey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;displayName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;App Key Check&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;health&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        &amp;quot;healthy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;lucid&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;displayName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Database&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;health&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        &amp;quot;healthy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        &amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;All connections are healthy&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;meta&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;connection&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;pg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Connection is healthy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;error&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the &lt;code&gt;lucid&lt;/code&gt; section we will see if our database connection is working or any applicable error information.&lt;/p&gt;
&lt;h2&gt;Defining Models&lt;/h2&gt;
&lt;p&gt;Once we&amp;#39;ve configured our database, we will want to interact with the data in it. Lucid makes use of &lt;code&gt;models&lt;/code&gt; essentially as proxies for database tables. We can generate a &lt;code&gt;model&lt;/code&gt; for our &lt;code&gt;User&lt;/code&gt; with &lt;code&gt;ace&lt;/code&gt; as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Stop your development server with &lt;code&gt;ctrl + c&lt;/code&gt; before running this:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; make:model&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; User&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above script will have generated a &lt;code&gt;User&lt;/code&gt; model class in the &lt;code&gt;app/Models/User.ts&lt;/code&gt; file that extends &lt;code&gt;BaseModel&lt;/code&gt;. All models must do this. The generated &lt;code&gt;User.ts&lt;/code&gt; file looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;User.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DateTime } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;luxon&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { BaseModel, column } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@ioc:Adonis/Lucid/Orm&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; BaseModel&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  @&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;column&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;({ &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;isPrimary: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  @&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;column&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateTime&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;({ &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;autoCreate: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; createdAt&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DateTime&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  @&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;column&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateTime&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;({ &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;autoCreate: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;autoUpdate: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; updatedAt&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DateTime&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;When viewing the above file your code editor may give you a warning saying that decorators are not supported, if you see this then set the &lt;code&gt;experimentalDecorators&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt; in your &lt;code&gt;tsconfig.json&lt;/code&gt; file:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;compilerOptions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;experimentalDecorators&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Note the &lt;code&gt;@column&lt;/code&gt; decorators, these are used to map columns in our database to our model fields. We&amp;#39;ll add a field for our user&amp;#39;s &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;User.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; BaseModel&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // ... other stuff in class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  @&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;column&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  @&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;column&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Any properties or methods defined in a class without the &lt;code&gt;@column&lt;/code&gt; decorator will not be mapped to the database, we can just use these as normal functions in the class and implement utilities from them&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Migrating the Database&lt;/h2&gt;
&lt;p&gt;At this point, our database does not contain a &lt;code&gt;user&lt;/code&gt; table, which will be used to store our data for the &lt;code&gt;User&lt;/code&gt; model. We need to create a Database Migration which will add the required table and fields.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ace&lt;/code&gt; provides us with a method to scaffold a migration file. To create this file we will run the following command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; make:migration&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which will have created a &lt;code&gt;database/migrations/SOME_ID_users.ts&lt;/code&gt; file with the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;*_users.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; BaseSchema &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@ioc:Adonis/Lucid/Schema&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Users &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; BaseSchema&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  protected&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;users&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; up&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.schema.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createTable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.tableName, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;increments&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;timestamps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; down&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.schema.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dropTable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.tableName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The generated file (above) contains an &lt;code&gt;up&lt;/code&gt; function which will create a &lt;code&gt;users&lt;/code&gt; table with an &lt;code&gt;id&lt;/code&gt; as well as &lt;code&gt;createdAt&lt;/code&gt; and &lt;code&gt;updatedAt&lt;/code&gt; fields. We will need to modify the &lt;code&gt;up&lt;/code&gt; function to add our new fields as well:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Users &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; BaseSchema&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; up&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.schema.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createTable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.tableName, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;increments&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;timestamps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // our added fields&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;notNullable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;unique&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;notNullable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once we&amp;#39;ve defined our migration script we need to build the application with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then we can run the migration using &lt;code&gt;ace&lt;/code&gt; as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ace&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; migration:run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;If there is an error in a migration script, we can rollback the migration with &lt;code&gt;node ace migration:rollback&lt;/code&gt; which will run the &lt;code&gt;down&lt;/code&gt; function in your migration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Interact with the Database&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve got our database, we can interact with it using the &lt;code&gt;User&lt;/code&gt; model we defined earlier&lt;/p&gt;
&lt;p&gt;The first change we&amp;#39;ll make is to modify the &lt;code&gt;get&lt;/code&gt; function to return all users. To do this we need to import &lt;code&gt;App/Models/User&lt;/code&gt; and use the &lt;code&gt;User.all&lt;/code&gt; method:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; User &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;App/Models/User&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UsersController {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // get all users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; User.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;all&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;We use &lt;code&gt;await&lt;/code&gt; because the &lt;code&gt;User.all&lt;/code&gt; function is asynchronous&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next, we&amp;#39;ll add a function to create a &lt;code&gt;User&lt;/code&gt;. We will call it &lt;code&gt;post&lt;/code&gt;. To make this function work we need to do a couple of things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Import &lt;code&gt;HttpContextContract&lt;/code&gt; from &lt;code&gt;@ioc:Adonis/Core/HttpContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Retrieve the &lt;code&gt;request&lt;/code&gt; from the &lt;code&gt;HttpContextContract&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Return the created user&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { HttpContextContract } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@ioc:Adonis/Core/HttpContext&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ... other imports&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UsersController {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // ... get user code above&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; post&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;({ request }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HttpContextContract) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // get the user from the request body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; request.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;all&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // create a user using the object we received&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; User.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(newUser)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // return the created user object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;request.all&lt;/code&gt; function combines the data from the request body and query string into a single object&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When we&amp;#39;ve added that, our completed &lt;code&gt;UsersController.ts&lt;/code&gt; file should look like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UsersController.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { HttpContextContract } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@ioc:Adonis/Core/HttpContext&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; User &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;App/Models/User&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UsersController {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; User.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;all&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; post&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;({ request }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HttpContextContract) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; request.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;all&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; User.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(newUser)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we&amp;#39;ve added a new function to our controller, we need to expose a route to it in the &lt;code&gt;routes.ts&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;routes.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Route.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;post&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;users&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;UsersController.post&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Consume the API&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve created API endpoints for listing all users and creating a user we can restart our development server with &lt;code&gt;npm start&lt;/code&gt; and consume our API from wherever we want to make some HTTP requests&lt;/p&gt;
&lt;h3&gt;Create a User&lt;/h3&gt;
&lt;p&gt;To create a &lt;code&gt;User we need to make a&lt;/code&gt;POST&lt;code&gt;request to&lt;/code&gt;&lt;a href=&quot;http://localhost:3333/users%60and&quot; &gt;http://localhost:3333/users`and&lt;/a&gt; a Content-Type of&lt;code&gt;application/json&lt;/code&gt;with the following as the&lt;code&gt;body&lt;/code&gt; for our request:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Bob Smith&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;email&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob@smithmail.com&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which should return a created user like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Bob Smith&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;email&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob@smithmail.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;created_at&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2020-07-26T14:35:25.987-00:00&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;updated_at&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2020-07-26T14:35:25.988-00:00&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;We can also try to create a &lt;code&gt;User&lt;/code&gt; with the same information but we will see that this fails due to the database constraints we added in our migration script&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next, we can get a list of all Users by making a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;http://localhost:333/users&lt;/code&gt; which should give us back our created users:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;created_at&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2020-07-26T14:35:25.987-00:00&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;updated_at&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2020-07-26T14:35:25.988-00:00&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Bob Smith&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;email&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob@smithmail.com&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;My overall impression of AdonisJS is pretty good. The framework feels very stable and I had much fewer issues in the process of learning it and writing this post than I have had using other more popular frameworks.&lt;/p&gt;
&lt;p&gt;AdonisJS is very well documented with code samples for most traditional tasks and is backed by some solid libraries for things like database integration&lt;/p&gt;
&lt;p&gt;Working with SQL using the framework has been fairly straightforward, and the ability to write database migrations using functionality provided by the framework instead of just tossing some wild SQL together makes it more approachable&lt;/p&gt;
&lt;p&gt;Personally, however, I prefer no-SQL databases like MongoDB and tend to use them more often when using JavaScript or TypeScript, but I feel like if the need arises for a SQL database then AdonisJS is a really good option, especially if you&amp;#39;re a JavaScript developer and don&amp;#39;t want to have to learn Java or C# for this type of functionality&lt;/p&gt;
&lt;p&gt;There is also a &lt;strong&gt;lot&lt;/strong&gt; more functionality than what I&amp;#39;ve gone through in this post, so I&amp;#39;d recommend browsing &lt;a href=&quot;https://preview.adonisjs.com/&quot; &gt;the AdonisJS docs&lt;/a&gt; to get a broader sense of what the framework entails&lt;/p&gt;
&lt;p&gt;If you feel like playing around with the code I&amp;#39;ve gone through in this post without having to write it all then I&amp;#39;ve got it all &lt;a href=&quot;https://github.com/nabeelvalley/blog-code/tree/post/adonisjs-first-look&quot; &gt;on GitHub&lt;/a&gt; and it should just be plug-and-play using Visual Studio Code Remote Containers. If you want to learn more about that, then you can check out &lt;a href=&quot;/blog/2020/25-07/developing-in-a-container-vscode/&quot; &gt;my previous blog post&lt;/a&gt; on developing within a container&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Colour in Black and White Photography</title><link>https://nabeelvalley.co.za/blog/2020/07-04/filtering-in-bw.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/07-04/filtering-in-bw.html</guid><description>Introduction to Black and White Colour Filtering and Processing for Photography</description><pubDate>Tue, 07 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Colour in Black and White Photography&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Let&amp;#39;s talk about black and white shall we?. As a first-time monochromer there are a couple of aspects of shooting and editing a black and white picture that isn&amp;#39;t immediately apparent&lt;/p&gt;
&lt;p&gt;When shooting in Black and White (henceforth B&amp;amp;W) there are some things we need to be aware especially aware of, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Brightness&lt;/li&gt;
&lt;li&gt;Texture&lt;/li&gt;
&lt;li&gt;Colour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, of course, other considerations can be made but most of these boil down to how you use these three elements. For the most part, I&amp;#39;ll be discussing how &lt;em&gt;colour&lt;/em&gt; comes into play from an editing perspective, but this should give you an awareness of how this applies when shooting too&lt;/p&gt;
&lt;h2&gt;Brightness&lt;/h2&gt;
&lt;p&gt;When I refer to brightness in this context I am not referring to the exposure of the image but rather the distribution of brightness across the image itself, where are your shadows and highlights, how bright is your subject in relation to your background, etc.&lt;/p&gt;
&lt;p&gt;Typically when we are working with a B&amp;amp;W image we try to have our subject be a little brighter (or much brighter) than everything else, this helps us to draw the viewer&amp;#39;s attention more easily, of course, this is only one of the factors&lt;/p&gt;
&lt;h2&gt;Texture&lt;/h2&gt;
&lt;p&gt;When shooting B&amp;amp;W we also look for texture, I would argue that texture is to a black and white picture what colour is to a colour one. Texture helps us to differentiate between different elements in a photo and is very evident when used a lot of strong contrast. Sometimes you want a lot of texture, sometimes you don&amp;#39;t - it is, however, important that you acknowledge how it contributes to an image&lt;/p&gt;
&lt;h2&gt;Colour&lt;/h2&gt;
&lt;p&gt;My focus in this post is primarily colour because I think it&amp;#39;s the easiest to play around with and can make the biggest impact to a picture when editing (how else does anyone get B&amp;amp;W these days?)&lt;/p&gt;
&lt;p&gt;At a simplified level, the way we work with colour in a B&amp;amp;W picture is by manipulating the brightness with which different colours are interpreted which in turn allows us to emphasize (or de-emphasize) specific elements in an image&lt;/p&gt;
&lt;p&gt;Over the remainder of this post I&amp;#39;ll be discussing a lot of this in the context of the following image:&lt;/p&gt;
&lt;center&gt;&lt;p&gt;&lt;img aspect-ratio=&quot;0.6650390625&quot; orientation=&quot;vertical&quot; alt=&quot;colour&quot; src=&quot;/optimized-images/public/content/blog/2020/07-04/images/colour.webp&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;For our discussion there are a few important aspects of this image to note:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The image is darkest in the background (top left) and transitions to being brighter in the foreground (bottom right)&lt;/li&gt;
&lt;li&gt;We primarily have the subject in &lt;strong&gt;red&lt;/strong&gt; and the background element (leaves) in &lt;strong&gt;green&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The brightness of our red and green elements in their respective sections of the image are approximately the same&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we were to simply convert this image to a B&amp;amp;W one we get the following:&lt;/p&gt;
&lt;center&gt;&lt;p&gt;&lt;img aspect-ratio=&quot;0.6650390625&quot; orientation=&quot;vertical&quot; alt=&quot;neutral&quot; src=&quot;/optimized-images/public/content/blog/2020/07-04/images/neutral.webp&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;From the above we see that the distinction between our red and green elements isn&amp;#39;t really visible anymore, this is because of the impact that colour mixing has on our image. Mixing allows us to control the way the different colours are seen in the image and most photo editing tools have some version of a Black and White Mixer that allows us to apply a colour filter to a Black and White image&lt;/p&gt;
&lt;h3&gt;Neutral Filtering&lt;/h3&gt;
&lt;p&gt;This is the &amp;quot;natural&amp;quot; way that a B&amp;amp;W conversion works, using this method for any two colours at approximately the same brightness we should see the same brightness in the B&amp;amp;W version&lt;/p&gt;
&lt;p&gt;If we look at the neutral version of our image we can observe that the brightness across our image is fairly consistent with that of the colour version with a darker background and brighter foreground. We can also see that there is very little differentiation between the red and green elements in our image&lt;/p&gt;
&lt;center&gt;&lt;p&gt;&lt;img src=&quot;/content/blog/2020/07-04/images/neutral.svg&quot; alt=&quot;Neutral Version of Discussion Image&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;In photography, there are few well-known colour filters which can be placed in front of your lens to achieve what we are doing here digitally. Commonly we have red, green, blue, and yellow filters. We&amp;#39;ll just be looking at the red and green filters that were used to edit this image&lt;/p&gt;
&lt;h3&gt;Red Filter&lt;/h3&gt;
&lt;p&gt;In a picture like this where our subject is red, we can use a red filter to increase the brightness of the red portions of our image. To do this we would bump up the red and orange sections of our colours while trying to maintain a smooth change from one colour to the next to prevent any sharp changes in the brightness of our image&lt;/p&gt;
&lt;p&gt;Additionally, I&amp;#39;ve also made the green slightly darker to add some additional contrast. We can see the result of doing so along with the changes made to the brightness of the respective colours below:&lt;/p&gt;
&lt;center&gt;&lt;p&gt;&lt;img src=&quot;/content/blog/2020/07-04/images/red.svg&quot; alt=&quot;Red Filtered Version of Discussion Image&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;Using a method like this we can draw our focus back to the red elements a little more than if we had left the brightnesses as they were in the Neutral image while pushing down the brightness of our green elements so we don&amp;#39;t have the two competing for focus&lt;/p&gt;
&lt;h3&gt;Green Filter&lt;/h3&gt;
&lt;p&gt;We can also do something like the above using a filter that brightens the green and darkens the red&lt;/p&gt;
&lt;center&gt;&lt;p&gt;&lt;img src=&quot;/content/blog/2020/07-04/images/green.svg&quot; alt=&quot;Green Filtered Version of Discussion Image&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;In the resulting image above we can see that the greens are now much brighter and the reds are almost black - however we still maintain a good level of contrast between our too resulting elements. We can see a comparison of the impact the different colour filters have on our image below. These are ordered from left to right as red, neutral and green&lt;/p&gt;
&lt;center&gt;&lt;p&gt;&lt;img aspect-ratio=&quot;2.0&quot; orientation=&quot;horizontal&quot; alt=&quot;comparison&quot; src=&quot;/optimized-images/public/content/blog/2020/07-04/images/comparison.webp&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;Using what we&amp;#39;ve looked at in the above we can see that the way we choose to filter a black and white image has a huge impact on how we direct the viewer&amp;#39;s attention in our image as well as how clearly we can differentiate between different elements&lt;/p&gt;
&lt;p&gt;Note that while we do have different common colour filters, when editing a B&amp;amp;W image it usually makes sense to play around with your Black and White Mixer Tool to see what works best for your image&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Package Management with Poetry</title><link>https://nabeelvalley.co.za/blog/2020/07-10/python-packages-with-poetry.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/07-10/python-packages-with-poetry.html</guid><description>Manage python packages using poetry</description><pubDate>Wed, 07 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Package Management with Poetry&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://python-poetry.org/docs/&quot; &gt;Poetry Docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Python package management is typically quite a mess. Managing packages with &lt;code&gt;pip&lt;/code&gt; often requires additional management of things like virtual environments and python version management&lt;/p&gt;
&lt;p&gt;Poetry is a package manager that abstracts a lot of the typical Python dependency and environment management away from the user&lt;/p&gt;
&lt;h2&gt;Install Poetry&lt;/h2&gt;
&lt;p&gt;Before you can install &lt;code&gt;poetry&lt;/code&gt; you need to have Python installed&lt;/p&gt;
&lt;p&gt;To install &lt;code&gt;poetry&lt;/code&gt; you can do one of the following depending on your OS:&lt;/p&gt;
&lt;h3&gt;Windows Powershell&lt;/h3&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ps1&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Invoke-WebRequest&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Uri https:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;//&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;raw.githubusercontent.com&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;python&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;master&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;get-poetry&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.py &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;UseBasicParsing).Content &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; python &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Bash&lt;/h3&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;curl&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -sSL&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; python&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; -&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Initialize Poetry&lt;/h2&gt;
&lt;h3&gt;Create a New Project&lt;/h3&gt;
&lt;p&gt;If you&amp;#39;re starting a new project, you can run the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-project&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above will generate a &lt;code&gt;pyproject.toml&lt;/code&gt; file with the project settings. Alternatively you can use the following to add &lt;code&gt;poetry&lt;/code&gt; to an existing project&lt;/p&gt;
&lt;h3&gt;Add to Existing Project&lt;/h3&gt;
&lt;p&gt;To add &lt;code&gt;poetry&lt;/code&gt; to an existing project, run the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; init&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Using Poetry&lt;/h2&gt;
&lt;h3&gt;Add Dependency&lt;/h3&gt;
&lt;p&gt;To manage dependencies you can use the &lt;code&gt;poetry add&lt;/code&gt; command. For example, if we would like to install &lt;code&gt;flask&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; flask&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Run Application&lt;/h3&gt;
&lt;p&gt;To run an application using the virtual environment created by &lt;code&gt;poetry&lt;/code&gt; you can use the &lt;code&gt;poetry run&lt;/code&gt; command, followed by the command you want to run:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; python&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; app.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Running a &lt;code&gt;flask&lt;/code&gt; app would look something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; flask&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Create a Shell&lt;/h2&gt;
&lt;p&gt;To create a shell in the &lt;code&gt;poetry&lt;/code&gt; virtual environment run:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;poetry&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above will open a &lt;code&gt;poetry&lt;/code&gt; shell with the virtual environment. You can then do something like run the &lt;code&gt;python&lt;/code&gt; command to open a &lt;code&gt;python&lt;/code&gt; shell in the environment&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Trust .NET Core Dev Certificates</title><link>https://nabeelvalley.co.za/blog/2020/07-10/trust-dotnet-dev-certs.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/07-10/trust-dotnet-dev-certs.html</guid><description>Adding .NET Core Certificates to the Cert store from the CLI</description><pubDate>Wed, 07 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Trust .NET Core Dev Certificates&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When developing .NET Core web applications with HTTPS, to simplifiy your experience and avoid browser warnings you can trust the .NET Core dev certs on your local device with the followning commands:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; dev-certs&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; https&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; dev-certs&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; https&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --trust&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Capture Fetch with Cypress</title><link>https://nabeelvalley.co.za/blog/2020/10-11/capture-fetch-response-cypress.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/10-11/capture-fetch-response-cypress.html</guid><description>Capture and Use Fetch Requests and Responses in Cypress</description><pubDate>Tue, 10 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Capture Fetch with Cypress&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;To capture the result of a &lt;code&gt;fetch&lt;/code&gt; request with Cypress you will need to make use of &lt;code&gt;cy.route2&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;cy.route2&lt;/code&gt; command needs to be enabled in your &lt;code&gt;cypress.json&lt;/code&gt; file before usage, to do so add the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cypress.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;experimentalNetworkStubbing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;Next, using the command to capture requests to a route looks a bit like this in a test:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;cy.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;route2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;/do-stuff&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above you need to use the &lt;code&gt;cy.route2&lt;/code&gt; function. In the above we&amp;#39;re capturing &lt;code&gt;POST&lt;/code&gt; requests to the &lt;code&gt;/do-stuff&lt;/code&gt; endpoint. The object which contains the request and response data is stored in the &lt;code&gt;@data&lt;/code&gt; which can be retreived and worked with like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;cy.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;wait&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;@data&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;then&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do stuff using the data object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;cy.wait&lt;/code&gt; function retreives the &lt;code&gt;data&lt;/code&gt; object, we use the &lt;code&gt;.then&lt;/code&gt; function with a callback function to do stuff with the fully resolved &lt;code&gt;data&lt;/code&gt; object&lt;/p&gt;
&lt;p&gt;Furthermore, the HTTP response from the &lt;code&gt;data&lt;/code&gt; object can be parsed using &lt;code&gt;JSON.parse&lt;/code&gt;, you can then also add assertions based on the response object. Adding this in, the above code would look more like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;cy.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;wait&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;@data&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;then&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // parse the response body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; res&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data.response.body)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // assertions on the response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  assert.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isTrue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(res.success)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  assert.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isNotNull&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(res.message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Automate Anything with GitHub Actions</title><link>https://nabeelvalley.co.za/blog/2020/11-08/automate-anything-with-actions.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/11-08/automate-anything-with-actions.html</guid><description>Build a GitHub action that updates your Twitter Profile</description><pubDate>Tue, 11 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Automate Anything with GitHub Actions&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;&lt;img src=&quot;https://github.com/nabeelvalley/twitter-bio-update/workflows/Build%20Action%20Dist/badge.svg&quot; alt=&quot;Build Action Dist&quot; &gt;
&lt;img src=&quot;https://github.com/nabeelvalley/twitter-bio-update/workflows/Run%20Twitter%20Bio%20Action/badge.svg&quot; alt=&quot;Run Twitter Bio Action&quot; &gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can take a look at the Action we build in this post &lt;a href=&quot;https://github.com/nabeelvalley/twitter-bio-update/actions&quot; &gt;here on GitHub&lt;/a&gt;. I&amp;#39;ve also included an action that&amp;#39;s responsible for building and updating the action &lt;code&gt;dist&lt;/code&gt; which may also be of interest. It&amp;#39;s all in &lt;a href=&quot;https://github.com/nabeelvalley/twitter-bio-update&quot; &gt;this Repository&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A few weeks ago I was playing around with GitHub actions and the recently introduced GitHub Account README functionality and wanted a way to make this &amp;quot;static&amp;quot; file a bit more dynamic&lt;/p&gt;
&lt;p&gt;Enter GitHub Actions. GitHub actions are a way for you to define and run programmatic tasks. If you can put it in code, then you can run it as an action&lt;/p&gt;
&lt;p&gt;Usually, you&amp;#39;ll be using actions that have been defined by GitHub or another developer for common tasks, such as running your application CI or deployment processes. However, since actions are &lt;strong&gt;extremely&lt;/strong&gt; generic, we&amp;#39;re going to do something a little different - update our Twitter bio?&lt;/p&gt;
&lt;p&gt;In this post, we&amp;#39;re going create a GitHub action that uses the Twitter API to update our bio, as well as make the action we created run automatically on GitHub&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a GitHub Repository for us to work in&lt;/li&gt;
&lt;li&gt;Set up Twitter Developer Credentials&lt;/li&gt;
&lt;li&gt;Write a Node.js script that uses the Twitter API&lt;/li&gt;
&lt;li&gt;Configure our GitHub Action Metadata&lt;/li&gt;
&lt;li&gt;Add our Twitter Secrets in GitHub&lt;/li&gt;
&lt;li&gt;Configure a GitHub Action that will run our script (an action, within an action)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://git-scm.com/downloads&quot; &gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://nodejs.org/&quot; &gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot; &gt;Visual Studio Code&lt;/a&gt; or any other Code Editor&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Create a GitHub Repo&lt;/h2&gt;
&lt;p&gt;For us to run our action we&amp;#39;ll need a GitHub Repository to use, to create a Repo go to &lt;a href=&quot;https://github.com/&quot; &gt;GitHub&lt;/a&gt; and sign in, thereafter go the &lt;a href=&quot;https://github.com/new&quot; &gt;&amp;#39;Create a new repository page&amp;#39;&lt;/a&gt; and fill in the details, be sure to select &lt;code&gt;Initialize this repository with a README&lt;/code&gt;, pick &lt;code&gt;Node&lt;/code&gt; as the &lt;code&gt;.gitignore&lt;/code&gt; file, and select a license if you&amp;#39;d like to&lt;/p&gt;
&lt;p&gt;Once you&amp;#39;ve done that, click &lt;code&gt;Create repository&lt;/code&gt; and you should see the initial files we added to the Repo. Next, click on the &lt;code&gt;Code&lt;/code&gt; button and copy the URL in the text box&lt;/p&gt;
&lt;p&gt;Now, from a terminal, you will need to clone the repository. Run the following command and make sure to paste the link you just copied in place of &lt;code&gt;&amp;lt;YOUR URL&amp;gt;&lt;/code&gt; below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; clone&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;YOUR&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; UR&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;L&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, open the folder you just cloned in your code editor and create a new file called &lt;code&gt;.env&lt;/code&gt; in the folder root directory. We&amp;#39;ll keep our Twitter credentials in this file for testing. For now, just add the following to the file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_CONSUMER_KEY&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_CONSUMER_SECRET&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_ACCESS_KEY&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the next step, we&amp;#39;re going to get the credentials from Twitter, we&amp;#39;ll add them into the file above when we&amp;#39;re done&lt;/p&gt;
&lt;h2&gt;Get Some Twitter Cred.&lt;/h2&gt;
&lt;p&gt;Twitter exposes the Twitter Developer API that allows us to do all kinds of useful and pointless things by interacting with Twitter&amp;#39;s data&lt;/p&gt;
&lt;p&gt;For us to consume the Twitter API we require credentials for the API. To set these up we&amp;#39;ll need to do a few things&lt;/p&gt;
&lt;p&gt;First, open your browser on &lt;a href=&quot;https://developer.twitter.com/&quot; &gt;the Twitter Developer Portal&lt;/a&gt; and click the sign-in button. Then, once you&amp;#39;ve signed in, you should see your name on the top right of the page, click on the dropdown arrow and select &lt;code&gt;Apps&lt;/code&gt; to go to the App Dashboard&lt;/p&gt;
&lt;p&gt;On the App Dashboard, click &lt;code&gt;Create an app&lt;/code&gt; and fill in the &lt;strong&gt;required&lt;/strong&gt; information. For the &lt;code&gt;Website URL&lt;/code&gt; you can put the URL of your GitHub repository that you copied previously into this field. Once you&amp;#39;ve filled in all the details click &lt;code&gt;Create&lt;/code&gt; at the bottom of the page&lt;/p&gt;
&lt;p&gt;You should now see the Details Page for the app we just created. Next, click on the &lt;code&gt;Keys and Tokens&lt;/code&gt; tab and click &lt;code&gt;Generate&lt;/code&gt; then copy and paste each token after the &lt;code&gt;=&lt;/code&gt; in the &lt;code&gt;.env&lt;/code&gt; file we created without any spaces before or after the key&lt;/p&gt;
&lt;p&gt;When you&amp;#39;ve pasted your tokens into their places, your &lt;code&gt;.env&lt;/code&gt; file should look something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that using the template for &lt;code&gt;.gitignore&lt;/code&gt; that we chose, the &lt;code&gt;.env&lt;/code&gt; file will be automatically ignored. Don&amp;#39;t publically upload this data just anywhere as it can potentially give someone access to your Twitter account&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_CONSUMER_KEY&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;xxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_CONSUMER_SECRET&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;xxxxxxxxxxxxxxxxxxx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_ACCESS_KEY&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;xxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;xxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;(With the actual keys, and not just &lt;code&gt;xxxx&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve got our credentials set up, we can start to work on the application&lt;/p&gt;
&lt;h2&gt;Using the Twitter API&lt;/h2&gt;
&lt;p&gt;We&amp;#39;re going to be writing a script that runs on Node.js (JavaScript) and makes use of the Twitter API using the &lt;code&gt;twit&lt;/code&gt; library for Node.js and the GitHub libraries for working with GitHub actions&lt;/p&gt;
&lt;p&gt;To get started, run the following command from a terminal within your repository&amp;#39;s directory to initialize a new Node.js project and select the defaults for all the questions:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; init&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we&amp;#39;ll add the dependencies that our application is going to need to run:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@actions/core&lt;/code&gt; allows us to interact with the data provided to our action by GitHub&lt;/li&gt;
&lt;li&gt;&lt;code&gt;twit&lt;/code&gt; is used to interact with the Twitter API&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dotenv&lt;/code&gt; enables us to load in our &lt;code&gt;.env&lt;/code&gt; file so our application can use it&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; install&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; @actions/core&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; twit&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; dotenv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once the application is done installing we&amp;#39;ll create an &lt;code&gt;index.js&lt;/code&gt; file inside of our repo folder and we can get started on our code&lt;/p&gt;
&lt;p&gt;Inside of the &lt;code&gt;index.js&lt;/code&gt; the first thing we&amp;#39;ll want to do is import our environment variables from the &lt;code&gt;.env&lt;/code&gt; file we configured, we&amp;#39;ll do that using the &lt;code&gt;dotenv&lt;/code&gt; NPM Package we installed previously:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;dotenv&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;config&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we&amp;#39;ll configure a new &lt;code&gt;Twitter&lt;/code&gt; API Client using our environment variables. The &lt;code&gt;twitter&lt;/code&gt; Package exports a &lt;code&gt;Twitter&lt;/code&gt; class that we can create an instance of, do to this we will use the &lt;code&gt;Twitter&lt;/code&gt; constructor and get our environment variables that are all stored in the &lt;code&gt;process.env&lt;/code&gt; variable:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Twitter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;twitter&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; client&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Twitter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  consumer_key: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_CONSUMER_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  consumer_secret: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_CONSUMER_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  access_token_key: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_ACCESS_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  access_token_secret: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we&amp;#39;ve got an instance of a &lt;code&gt;Twitter&lt;/code&gt; client that we can use to interact with the API we&amp;#39;ll want to use it&lt;/p&gt;
&lt;p&gt;The Twitter API Client runs asynchronously, for us to work with it correctly we have two options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using the &lt;code&gt;callback&lt;/code&gt; method, which means that we give the &lt;code&gt;client&lt;/code&gt; a function to run when it&amp;#39;s done sending the data to Twitter. While this is easier in our specific circumstance it can become difficult to keep track of when we have many different callback functions&lt;/li&gt;
&lt;li&gt;The second option is to use &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; syntax, which allows us to write our code more sequentially and makes it easier for us to control our sequence and flow&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To use the &lt;code&gt;async/await&lt;/code&gt; functionality, we need the code that we need to &lt;code&gt;await&lt;/code&gt; to be inside of an &lt;code&gt;async&lt;/code&gt; function. In this one function, we can &lt;code&gt;await&lt;/code&gt; as many tasks as we want sequentially without worrying about callbacks&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll create a &lt;code&gt;main&lt;/code&gt; function that is &lt;code&gt;async&lt;/code&gt; in which we will do any asynchronous interactions, in our case - interact with Twitter&lt;/p&gt;
&lt;p&gt;After the code we&amp;#39;ve already got in our &lt;code&gt;index.js&lt;/code&gt; file, define the &lt;code&gt;main&lt;/code&gt; function as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // this is where we&amp;#39;ll work with the twitter client&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we&amp;#39;ll add the code to interact with the Twitter API inside of this function. To update our Profile Bio (or &lt;code&gt;description&lt;/code&gt; as it&amp;#39;s called in the Twitter API) we&amp;#39;ll make use of the &lt;code&gt;account/update_profile&lt;/code&gt; endpoint&lt;/p&gt;
&lt;p&gt;The data we send the Twitter API will need to be an object with a &lt;code&gt;description&lt;/code&gt; property for what we want to set our Twitter Bio as. We&amp;#39;ll &lt;code&gt;await&lt;/code&gt; this function call by adding it within our &lt;code&gt;main&lt;/code&gt; function:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;post&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;account/update_profile&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    description: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above code will set our Twitter &lt;code&gt;description&lt;/code&gt; to &lt;code&gt;Hello, World!&lt;/code&gt; and then print our the &lt;code&gt;response&lt;/code&gt; we get back from Twitter&lt;/p&gt;
&lt;p&gt;The way we&amp;#39;ve written the above code is a little bit dangerous as we aren&amp;#39;t handling any potential errors/failures that may happen when interacting with the Twitter API&lt;/p&gt;
&lt;p&gt;When working with an API via an HTTP Request there&amp;#39;s always the chance that there could be an error. Errors can be caused by anything ranging from poor network connections, incorrect credentials, or a system outage on the API host itself&lt;/p&gt;
&lt;p&gt;For our application to give us a bit more information about what happened, we may want to handle the error before passing it on to the process that kicked off our script. We&amp;#39;ll make use of a &lt;code&gt;try/catch&lt;/code&gt; to handle this error:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;post&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;account/update_profile&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      description: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(error)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      `The Twitter API Responded with an Error: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can see above that we&amp;#39;re just doing some cleanup of the error message before throwing the exception to the process&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve fully defined our &lt;code&gt;client&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; functions we can call the function as the last line of the script:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This should make a request to the Twitter API and print our the &lt;code&gt;response&lt;/code&gt; or &lt;code&gt;error&lt;/code&gt; if there is one&lt;/p&gt;
&lt;p&gt;So, the above function will always set our Twitter Bio to the same value, this isn&amp;#39;t interesting. Next, we&amp;#39;d like to get some data from the workflow that&amp;#39;s going to be running our action. The way we would do this is with an &lt;code&gt;input&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Our action is going to take an &lt;code&gt;input&lt;/code&gt; called &lt;code&gt;bio&lt;/code&gt;. We can use the &lt;code&gt;@actions/core&lt;/code&gt; library to get the value of the &lt;code&gt;input&lt;/code&gt;. We can do this with the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; core&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;@actions/core&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; bio&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; core.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getInput&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;bio&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above code also sets a default value of &lt;code&gt;Hello, World!&lt;/code&gt; to the description, this will allow us to also run the action without throwing an exception on our local machine as well as if the &lt;code&gt;bio&lt;/code&gt; is not provided to the action&lt;/p&gt;
&lt;p&gt;Furthermore, instead of just throwing errors, we can rather set the error-status using the &lt;code&gt;core.setFailed&lt;/code&gt; function. Updating our &lt;code&gt;main&lt;/code&gt; function to do this we now have:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;post&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;account/update_profile&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      description: bio,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(error)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    core.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setFailed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      `The Twitter API Responded with an Error: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Finally, our full &lt;code&gt;index.js&lt;/code&gt; file should look like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;re&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;dotenv&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;config&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Twitter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;twitter&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; core&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;@actions/core&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; bio&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; core.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getInput&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;bio&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; client&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Twitter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  consumer_key: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_CONSUMER_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  consumer_secret: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_CONSUMER_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  access_token_key: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_ACCESS_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  access_token_secret: process.env.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;post&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;account/update_profile&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      description: bio,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(error)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    core.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setFailed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      `The Twitter API Responded with an Error: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we&amp;#39;ve written the functionality for our action we&amp;#39;ll want to turn it into an action&lt;/p&gt;
&lt;h2&gt;Configure the Action Metadata&lt;/h2&gt;
&lt;p&gt;For GitHub to recognise our code as an action, we need to create an &lt;code&gt;action.yml&lt;/code&gt; file that contains a description of our action. Our &lt;code&gt;action.yml&lt;/code&gt; file needs to have the following information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt; for our action&lt;/li&gt;
&lt;li&gt;&lt;code&gt;description&lt;/code&gt; of the action itself&lt;/li&gt;
&lt;li&gt;an &lt;code&gt;input&lt;/code&gt; parameter of &lt;code&gt;bio&lt;/code&gt; that will be used by our application&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runs&lt;/code&gt; which states the script to run&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;action.yml&lt;/code&gt; file for our action looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;action.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Twitter Bio Update&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Update your Twitter Account Bio&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;inputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Text that you would like to set as your Twitter Bio&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    required&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;runs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  using&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;node12&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;index.js&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The fields we&amp;#39;ve got above are all pretty much required. The above fields are the simplest configuration for a Node.js action. The &lt;a href=&quot;https://docs.github.com/en/actions&quot; &gt;GitHub Docs&lt;/a&gt; have a lot more information on more complex configurations and actions&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve defined our action, we will want to configure it to run. But before we can do that, we&amp;#39;ll want to set up our secrets&lt;/p&gt;
&lt;h2&gt;Setting Up Secrets in GitHub&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve got our action defined, we&amp;#39;re almost ready to write a Workflow that will use this action. However, our action requires environment variables (that we&amp;#39;ve got saved in our &lt;code&gt;.env&lt;/code&gt; file) but we don&amp;#39;t want these to be pushed to GitHub as part of our source code. The way to set up these environment variables in GitHub is called a &lt;code&gt;secret&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To add our environment variables in GitHub you&amp;#39;ll need to open your Repo on GitHub and navigate to &lt;code&gt;Settings &amp;gt; Secrets&lt;/code&gt; then click &lt;code&gt;New secret&lt;/code&gt; and add your first secret. If we use our &lt;code&gt;.env&lt;/code&gt; file as a reference we&amp;#39;ll want to create a secret for each line in the file. To do this look at the name of the environment variable (everything before the &lt;code&gt;=&lt;/code&gt;) and set this as the &lt;code&gt;Name&lt;/code&gt; for the secret, then look at the value (everything after the &lt;code&gt;=&lt;/code&gt;) and set this as the &lt;code&gt;Value&lt;/code&gt; for the secret then click &lt;code&gt;Add secret&lt;/code&gt;. Do this for every line in your &lt;code&gt;.env&lt;/code&gt; file (every environment variable`&lt;/p&gt;
&lt;h2&gt;Create a Workflow&lt;/h2&gt;
&lt;p&gt;Workflows are GitHub&amp;#39;s way of tying together a bunch of actions to run. Often, we will want to run multiple actions. We place these into what&amp;#39;s called a &lt;code&gt;step&lt;/code&gt; in a &lt;code&gt;job&lt;/code&gt;. Each Workflow can have multiple &lt;code&gt;steps&lt;/code&gt; and &lt;code&gt;jobs&lt;/code&gt; and a repository can have multiple workflows&lt;/p&gt;
&lt;p&gt;The structure of a workflow is something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;workflow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|-- Job 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|   |-- Step 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|   |-- Step 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|-- Job 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    |-- Step 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;A Workflow can have any number of jobs and steps&lt;/p&gt;
&lt;p&gt;We&amp;#39;re going to create a Workflow with a single job with the goal of running our script. For us to do this, the job will need to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checkout our code&lt;/li&gt;
&lt;li&gt;Configure Node.js and NPM&lt;/li&gt;
&lt;li&gt;Install Dependencies&lt;/li&gt;
&lt;li&gt;Run our Action&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To do Steps 1 and 2 we&amp;#39;re going to use actions that are defined by GitHub. We&amp;#39;re going to go through our Workflow file working from the top-down as this is the order in which everything will be run&lt;/p&gt;
&lt;p&gt;Firstly, we&amp;#39;ll need to create a new directory in our Repository named &lt;code&gt;.github&lt;/code&gt; and inside of this another called &lt;code&gt;workflows&lt;/code&gt;. Inside of the &lt;code&gt;.github/workflows&lt;/code&gt; directory create a file named &lt;code&gt;main.yml&lt;/code&gt; (this can be any name so long as it&amp;#39;s a &lt;code&gt;yml&lt;/code&gt; file)&lt;/p&gt;
&lt;p&gt;Next, on the first line of this file we will define a name for our workflow like so:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Run Twitter Bio Action&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is the name that will be displayed when the workflow runs. Actions are run when a specific GitHub event happens (more about that &lt;a href=&quot;https://docs.github.com/en/actions/reference/events-that-trigger-workflows&quot; &gt;in the Docs&lt;/a&gt;). We&amp;#39;re going to configure our action to run manually only, so we will use the &lt;code&gt;workflow_dispatch&lt;/code&gt; event. After the &lt;code&gt;name&lt;/code&gt; in the &lt;code&gt;main.yml&lt;/code&gt; file, add the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  workflow_dispatch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    inputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Twitter Bio&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        required&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above, we set an &lt;code&gt;on&lt;/code&gt; event for &lt;code&gt;workflow_dispatch&lt;/code&gt; with an &lt;code&gt;input&lt;/code&gt; for &lt;code&gt;bio&lt;/code&gt; that we&amp;#39;re going to pass on to our action&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve got the workflow metadata defined, we&amp;#39;re going to add a &lt;code&gt;job&lt;/code&gt;. To do this, we&amp;#39;ll add a &lt;code&gt;jobs&lt;/code&gt; object with a name of &lt;code&gt;update-bio&lt;/code&gt;, a specification on what OS it needs to run on, and the &lt;code&gt;steps&lt;/code&gt; that will be a part of it:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;jobs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  update-bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    runs-on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;ubuntu-latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Update Twitter Bio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      # we&amp;#39;ll add the steps here in a moment&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can see above that we&amp;#39;re running on the &lt;code&gt;ubuntu-latest&lt;/code&gt; OS. Next, we&amp;#39;ll add the first step for checking out our code in the action. This will use &lt;code&gt;actions/checkout&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;steps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  - &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Checkout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    uses&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;actions/checkout@v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above, we give our step a &lt;code&gt;name&lt;/code&gt; which is for display purposes, and a &lt;code&gt;uses&lt;/code&gt; which says what action this step should use. In our case, we&amp;#39;re checking out our code using the &lt;code&gt;actions/checkout@v2&lt;/code&gt; action&lt;/p&gt;
&lt;p&gt;Next, we&amp;#39;ll want to configure Node.js and NPM because our action needs these to run. We can use the &lt;code&gt;actions/setup-node@v1&lt;/code&gt; for this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;- &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Setup Node.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  uses&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;actions/setup-node@v1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    node-version&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;12.x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In this action, we use the &lt;code&gt;with&lt;/code&gt; to state an &lt;code&gt;input&lt;/code&gt; that the action needs. In this case, we specify that we want to use a &lt;code&gt;node-version&lt;/code&gt; of &lt;code&gt;12.x&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now we&amp;#39;ve got Node.js and NPM, we need to install the dependencies for our action to run. We do this with the &lt;code&gt;npm install&lt;/code&gt; command like so:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;- &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Install Dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;npm install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And lastly, we will configure our action to run with the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;- &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Run Action&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  uses&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;./&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  env&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    TWITTER_CONSUMER_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_CONSUMER_KEY }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    TWITTER_CONSUMER_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_CONSUMER_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    TWITTER_ACCESS_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_ACCESS_KEY }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_ACCESS_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ github.event.inputs.bio }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In this last step we&amp;#39;re doing quite a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We&amp;#39;re setting a &lt;code&gt;name&lt;/code&gt; for our action&lt;/li&gt;
&lt;li&gt;We set a &lt;code&gt;uses&lt;/code&gt; to be &lt;code&gt;./&lt;/code&gt; which means we want to run the action at the root of our Repo (our &lt;code&gt;action.yml&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;We set the &lt;code&gt;env&lt;/code&gt;, these are the different environment variables we want to pass to the application. We use &lt;code&gt;${\{ ... }\}&lt;/code&gt; to mean that it&amp;#39;s a variable, and we use &lt;code&gt;secrets.variable&lt;/code&gt; to access the variable from the secrets we configured in the repository&lt;/li&gt;
&lt;li&gt;We use the &lt;code&gt;with&lt;/code&gt; to set the &lt;code&gt;bio&lt;/code&gt; from the input we give to the workflow on our &lt;code&gt;workflow_dispatch&lt;/code&gt; event. GitHub exposes this in the &lt;code&gt;github.event.inputs.bio&lt;/code&gt; variable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With the &lt;code&gt;Run Action&lt;/code&gt; step added, we&amp;#39;ve got a full workflow. The overall &lt;code&gt;main.yml&lt;/code&gt; file should have the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Run Twitter Bio Action&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  workflow_dispatch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    inputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Twitter Bio&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        required&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;jobs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  update-bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    runs-on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;ubuntu-latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Update Twitter Bio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      - &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Checkout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        uses&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;actions/checkout@v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      - &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Setup Node.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        uses&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;actions/setup-node@v1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          node-version&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;12.x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      - &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Install Dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;npm install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      - &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Run Action&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        uses&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;./&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        env&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          TWITTER_CONSUMER_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_CONSUMER_KEY }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          TWITTER_CONSUMER_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_CONSUMER_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          TWITTER_ACCESS_KEY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_ACCESS_KEY }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          TWITTER_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ secrets.TWITTER_ACCESS_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;        with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          bio&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${{ github.event.inputs.bio }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Run the Action&lt;/h2&gt;
&lt;p&gt;To run the action, we first need to get everything to GitHub. From Repo directory, in the terminal, run the following commands:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; commit&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -m&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;I made a GitHub Action!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; push&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then, go to your repository on GitHub and click on the &lt;code&gt;Actions&lt;/code&gt; tab. You should then see your Workflow listed. Click on your workflow name, and then the &lt;code&gt;Run workflow&lt;/code&gt; dropdown. Fill in your &lt;code&gt;Twitter Bio&lt;/code&gt;, wait for the workflow to complete and look at your Twitter profile!&lt;/p&gt;
&lt;p&gt;From GitHub, you are also able to inspect and view any logs or errors from a Workflow run. If the workflow fails you can also take a look at the output that was thrown by the step that resulted in the failure&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;And that&amp;#39;s about it. We&amp;#39;ve taken a look at how you can use GitHub actions to automate a pretty silly task, but there&amp;#39;s a lot more to using GitHub Actions, and the sky&amp;#39;s the limit in terms of what you can use them for&lt;/p&gt;
&lt;p&gt;Overall, GitHub actions aren&amp;#39;t too different from similar options like Azure Pipelines, Jenkins, or any other CI service. What makes them so useful is how easily they hook into the source control system and how well they work and are supported within the GitHub ecosystem&lt;/p&gt;
&lt;p&gt;That all being said, they&amp;#39;re not the easiest things to configure and it can take a while to get them right if you&amp;#39;re doing something especially complex. Overall they&amp;#39;re pretty cool and are a pretty good place to get started with automating tasks and working with things like continuous integration and deployments and I&amp;#39;d definitely recommend giving them a shot&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Scripting with FSharp</title><link>https://nabeelvalley.co.za/blog/2020/13-10/launch-fsi-from-terminal.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/13-10/launch-fsi-from-terminal.html</guid><description>Using the .NET CLI to use the F# Interactive console and run F# Scripts</description><pubDate>Tue, 13 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Scripting with FSharp&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Before you can use the following, you will need the &lt;a href=&quot;https://dotnet.microsoft.com/download&quot; &gt;.NET Core SDK installed&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Open the F# Interactive Console&lt;/h2&gt;
&lt;p&gt;To open an F# interactive console using the &lt;code&gt;dotnet&lt;/code&gt; CLI. You can run the following command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; fsi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that to end statements/execute in the F# Interactive console use &lt;code&gt;;;&lt;/code&gt; at the end of a line or section of code&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once in the console, running &lt;code&gt;#help;;&lt;/code&gt; from the &lt;code&gt;fsi&lt;/code&gt; console to view the help menu, and &lt;code&gt;#quit;;&lt;/code&gt; to quit the interactive session&lt;/p&gt;
&lt;p&gt;Additionally, you can write multi-line &lt;code&gt;F#&lt;/code&gt; code as well as just single line expressions. Each expression should be terminated with &lt;code&gt;;;&lt;/code&gt;. For example, you can write a function that will print some data into the console:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; printer s &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    printfn s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, you can call the function with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;printer &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which will execute the above code and output &lt;code&gt;Hello World&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Run an F# Script&lt;/h2&gt;
&lt;p&gt;F# scripts can be run using the &lt;code&gt;dotnet fsi&lt;/code&gt; command as well, followed by the path to an F# script file:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; fsi&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ./myscript.fsx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>The Gatsby Migration, pt.3 - Smart Pages</title><link>https://nabeelvalley.co.za/blog/2020/15-03/gatsby-migration-3.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/15-03/gatsby-migration-3.html</guid><description>Adding dynamic pages to a Gatsby site</description><pubDate>Sun, 15 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;The Gatsby Migration, pt.3 - Smart Pages&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;So far we&amp;#39;ve created the initial react application as with a few routes for our &lt;code&gt;Home&lt;/code&gt;, &lt;code&gt;Blog&lt;/code&gt;, and &lt;code&gt;404&lt;/code&gt; pages. In this post we&amp;#39;ll look at how we can set up our &lt;code&gt;Post&lt;/code&gt; component to render our pages dynamically based on the JSON data we have. We&amp;#39;ll also extend this so that we can have some more content in a markdown file that we&amp;#39;ll parse and add to our Gatsby data&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2020/21-01/gatsby-migration-1&quot; &gt;Creating the initial React App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2020/01-02/gatsby-migration-2&quot; &gt;Rendering the &amp;quot;Dumb&amp;quot; pages with Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendering the &amp;quot;Smart&amp;quot; page with Gatsby&lt;/strong&gt; (This post)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Setting Up&lt;/h2&gt;
&lt;p&gt;We&amp;#39;re going to make our data a little more complex by creating two additional markdown files in our &lt;code&gt;static/posts&lt;/code&gt; directory to enable us to have more content with each post&lt;/p&gt;
&lt;p&gt;Create the following markdown files in the application and align the names with our &lt;code&gt;post-1.json&lt;/code&gt; and &lt;code&gt;post-2.json&lt;/code&gt; files:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;static/posts/post-1.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;static/posts/post-2.md&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Gatsby Plugins&lt;/h2&gt;
&lt;p&gt;To read the data from our files we&amp;#39;re going to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; to read our files into the Gatsby Data Layer&lt;/li&gt;
&lt;li&gt;Define our own plugin that can read the file content, parse the markdown, and add it into the data layer&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Reading the File Metadata&lt;/h3&gt;
&lt;p&gt;To read our file data we will need to first install the &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; plugin. Plugins in Gatsby enable us to ingest or transform data in our application. We then make use of GraphQL to query the data from the relevant component&lt;/p&gt;
&lt;p&gt;Install the &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; plugin with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn add gatsby-source-filesystem&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then add the plugin configuration to the &lt;code&gt;gatsby-node.js&lt;/code&gt; file into the &lt;code&gt;plugins&lt;/code&gt; array:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gatsby-node.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`gatsby-source-filesystem`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    options&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`content`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        path&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;__dirname&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}/static/posts`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will read all the data from our &lt;code&gt;posts&lt;/code&gt; directory into the filesystem. We can now start the application back up with &lt;code&gt;yarn start&lt;/code&gt; and navigate to &lt;code&gt;http://localhost:8000/__graphql&lt;/code&gt; in our browser to view the GraphQL data. We should be able to see the GraphiQL interface&lt;/p&gt;
&lt;p&gt;From the GraphiQL interface run the following query to see the data from the files in our directory:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;graphql&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;query&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; PostData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  allFile&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    nodes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      extension&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      absolutePath&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This should yield the following JSON with our file meta data in it:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;data&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;allFile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;nodes&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;post-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;extension&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;absolutePath&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;C:/repos/cra-to-gatsby/static/posts/post-1.json&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;extension&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;absolutePath&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;C:/repos/cra-to-gatsby/static/posts/1.jpg&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;post-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;extension&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;md&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;absolutePath&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;C:/repos/cra-to-gatsby/static/posts/post-1.md&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        // file 2 data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Processing the Files&lt;/h3&gt;
&lt;p&gt;Now that we have our metadata for each file in the file system, we&amp;#39;re going to create a plugin that will allow us to read the file data and add it the GraphQL data layer&lt;/p&gt;
&lt;p&gt;In order to do this, create a &lt;code&gt;plugins&lt;/code&gt; directory in the root folder. Inside of the plugins directory create a folder and folder for our plugin.&lt;/p&gt;
&lt;p&gt;Create a new folder in the &lt;code&gt;plugins&lt;/code&gt; directory with another folder called &lt;code&gt;gatsby-transformer-postdata&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;From this directory run the following commands to initialize and link the yarn package:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;plugins/gatsby-transformer-postdata&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn init -y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn link&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We&amp;#39;ll also add the &lt;code&gt;showdown&lt;/code&gt; package which will allow us to convert the markdown into the HTML so we can render it with our &lt;code&gt;Post&lt;/code&gt; component&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn add showdown&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then create an &lt;code&gt;gatsby-node.js&lt;/code&gt; file in this directory with the following content:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/plugins/gatsby-transformer-postdata/gatsby-node.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fs&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; crypto&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;crypto&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; showdown&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;showdown&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;exports&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;onCreateNode&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;getNode&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;actions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createNodeField&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createNode&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; actions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // we&amp;#39;ll process the node data here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This exposes the &lt;code&gt;onCreateNode&lt;/code&gt; Gatsby API for our plugin. This is what Gatsby calls when creating nodes and we will be able to hook into this to create new nodes with all the data for each respective post based on the created file nodes&lt;/p&gt;
&lt;p&gt;From the &lt;code&gt;onCreateNode&lt;/code&gt; function we&amp;#39;ll do the following to create the new nodes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check if it is a markdown node&lt;/li&gt;
&lt;li&gt;Check if the JSON file exists&lt;/li&gt;
&lt;li&gt;Read file content&lt;/li&gt;
&lt;li&gt;Parse the metadata into an object&lt;/li&gt;
&lt;li&gt;Convert the markdown to HTML&lt;/li&gt;
&lt;li&gt;Get the name of the node&lt;/li&gt;
&lt;li&gt;Define the data for our node&lt;/li&gt;
&lt;li&gt;Create the new node using the &lt;code&gt;createNode&lt;/code&gt; function&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;gatsby-transformer-postdata/gatsby-node.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fs&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; crypto&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;crypto&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; showdown&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;showdown&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;exports&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;onCreateNode&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;actions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;loadNodeContent&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createNodeField&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createNode&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; actions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // 1. Check if it is a markdown node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (node.internal.mediaType &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;text/markdown&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jsonFilePath&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;absolutePath&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;slice&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.json`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(jsonFilePath)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // 2. Check if the JSON file exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (fs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;existsSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(jsonFilePath)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // 3. Read file content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; markdownFilePath&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; node.absolutePath&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; markdownContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; fs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;readFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(markdownFilePath, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jsonContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; fs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;readFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(jsonFilePath, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // 4. Parse the metadata into an object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; metaData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(jsonContent)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // 5. Convert the markdown to HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; converter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; showdown.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Converter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; html&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; converter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;makeHtml&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(markdownContent)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // 6. Get the name of the node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; node.name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // 7. Define the data for our node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nodeData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        name,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        html,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        metaData,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        slug: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`/blog/${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // 8. Create the new node using the `createNode` function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newNode&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        // Node data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        ...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;nodeData,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        // Required fields.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        id: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`RenderedMarkdownPost-${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        children: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        internal: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`RenderedMarkdownPost`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          contentDigest: crypto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createHash&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`md5`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;update&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(nodeData))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;digest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`hex`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      createNode&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(newNode)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;From the root directory you can clean and rerun the application:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, reload the GraphiQL at &lt;code&gt;http://localhost:8000/__graphql&lt;/code&gt; and run the following query to extract the data we just pushed into the node:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;graphql&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;query&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; AllPostData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  allRenderedMarkdownPost&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    nodes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      slug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      metaData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        title&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This should give us the relevant post data:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;data&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;allRenderedMarkdownPost&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;nodes&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;html&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;lt;p&amp;gt;Hello here is some content for Post 1&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;ol&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;li&amp;gt;Hello&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;li&amp;gt;World&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;/ol&amp;gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;post-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;slug&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/post-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;metaData&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;            &amp;quot;body&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world, how are you&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;            &amp;quot;image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/posts/1.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;            &amp;quot;title&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Post 1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;html&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;lt;p&amp;gt;Hello here is some content for Post 2&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;ol&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;li&amp;gt;Hello&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;li&amp;gt;World&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;/ol&amp;gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;post-2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;slug&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/post-2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;metaData&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;            &amp;quot;body&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world, I am fine&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;            &amp;quot;image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/posts/2.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;            &amp;quot;title&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Post 2&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Create Pages&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve got all our data for the pages in one place we can use the &lt;code&gt;onCreatePages&lt;/code&gt; API to create our posts, and the &lt;code&gt;Post&lt;/code&gt; component to render the pages&lt;/p&gt;
&lt;h3&gt;Setting Up&lt;/h3&gt;
&lt;p&gt;Before we really do anything we need to rename the &lt;code&gt;Blog.js&lt;/code&gt; file to &lt;code&gt;blog.js&lt;/code&gt; as well as create the &lt;code&gt;src/components&lt;/code&gt; directory and move the &lt;code&gt;Post.js&lt;/code&gt; file into it, you may need to restart your application again using &lt;code&gt;yarn start&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Create Pages Dynamically&lt;/h3&gt;
&lt;p&gt;In our site root create a &lt;code&gt;gatsby-node.js&lt;/code&gt; file which exposes an &lt;code&gt;onCreatePages&lt;/code&gt; function:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gatsby-node.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;path&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;exports&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createPages&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;graphql&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;actions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createPage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; actions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;From this function we need to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Query for the PostData using the &lt;code&gt;graphql&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;Create a page for each &lt;code&gt;renderedMarkdownPost&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;gatsby-node.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;path&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;exports&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createPages&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;graphql&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;actions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createPage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; actions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // 1. Query for the PostData using the `graphql` function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; graphql&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    query AllPostData {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      allRenderedMarkdownPost {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        nodes {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          slug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          metaData {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;            body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;            image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;            title&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  `&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  result.data.allRenderedMarkdownPost.nodes.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // 2. Create a page for each `renderedMarkdownPost`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    createPage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      path: node.slug,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      component: path.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`./src/components/Post.js`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      context: node,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Render the Page Data&lt;/h3&gt;
&lt;p&gt;From the Post component we need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Export the &lt;code&gt;query&lt;/code&gt; for the data&lt;/li&gt;
&lt;li&gt;Get the data for the Post&lt;/li&gt;
&lt;li&gt;Render the data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;components/post.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { graphql } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;gatsby&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; App &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../App&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Post&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // 2. Get the data for the Post&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; postData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.renderedMarkdownPost&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // 3. Render the data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Post&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          This is the &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;postData.slug&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; page&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;postData.metaData.title&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;          className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;markdown&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;          dangerouslySetInnerHTML&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{ __html: postData.html }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;App&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Post&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// 1. Export the `query` for the data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; query&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; graphql&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  query PostData($slug: String!) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    renderedMarkdownPost(slug: { eq: $slug }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      slug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      metaData {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        title&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;From the &lt;code&gt;Post&lt;/code&gt; component above we use the &lt;code&gt;slug&lt;/code&gt; to determine which page to render, we also set the HTML content for the &lt;code&gt;markdown&lt;/code&gt; element above using the HTML we generated. We also now have our pages dynamically created based on the data in our &lt;code&gt;static&lt;/code&gt; directory&lt;/p&gt;
&lt;p&gt;You can also see that we have significantly reduced the complexity in the &lt;code&gt;Post&lt;/code&gt; component now that we don&amp;#39;t need to handle the data fetching from the component&lt;/p&gt;
&lt;p&gt;If you look at the site now you should be able to navigate through all the pages as you&amp;#39;d expect to be able to&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;By now we have completed the the entire migration process - converting our static and dynamic pages to use Gatsby. In order to bring the dynamic page generation functionality to our site we&amp;#39;ve done the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Used the &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; plugin to read our file data&lt;/li&gt;
&lt;li&gt;Created a local plugin to get the data for each post and convert the markdown to HTML&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;onCreatePages&lt;/code&gt; API to dynamically create pages based on the post data&lt;/li&gt;
&lt;li&gt;Update the &lt;code&gt;Post&lt;/code&gt; component to render from the data supplied by the &lt;code&gt;graphql&lt;/code&gt; query&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that&amp;#39;s about it, through this series we&amp;#39;ve covered most of the basics on building a Gatsby site and handling a few scenarios for processing data using plugins and rendering content using Gatsby&amp;#39;s available APIs&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Code for Noobs</title><link>https://nabeelvalley.co.za/blog/2020/17-05/code-for-noobs.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/17-05/code-for-noobs.html</guid><description>An introduction to programming and general programming concepts using JavaScript</description><pubDate>Sun, 17 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Code for Noobs&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;So I&amp;#39;ve been meaning to write an introductory post about the basics of JavaScript for quite some time. A few weeks ago I managed to finally get something going on &lt;a href=&quot;https://twitter.com/not_nabeel/status/1255743195557888000&quot; &gt;this Twitter thread (@not_nabeel)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s get into it&lt;/p&gt;
&lt;h2&gt;0. What is Programming&lt;/h2&gt;
&lt;p&gt;Programming is our way of telling a computer to do things. This can be anything from checking our spelling to making trippy digital art&lt;/p&gt;
&lt;p&gt;The basics of programming are the same in most languages and doesn&amp;#39;t involve much math or binary (&lt;code&gt;0010101&lt;/code&gt;) like a lot of people seem to think. Programming languages &lt;em&gt;usually&lt;/em&gt; make use of a very small subset of words and concepts of a normal human language like English&lt;/p&gt;
&lt;p&gt;The language I&amp;#39;m going to be using is called &lt;code&gt;JavaScript&lt;/code&gt; but many of these concepts are the same in most other programming languages&lt;/p&gt;
&lt;h2&gt;1. What is JavaScript?&lt;/h2&gt;
&lt;p&gt;JavaScript is the language used to add interactivity to a website but it can also be used to do pretty much anything you like. JavaScript runs in all modern web browsers and can be accessed through your browser&amp;#39;s developer tools, but it can also be used on other devices using something like &lt;a href=&quot;https://twitter.com/nodejs&quot; &gt;@nodejs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For our purposes though, we don&amp;#39;t need to worry too much about how that all works right now. To get started we&amp;#39;ll be using tools like &lt;a href=&quot;https://twitter.com/CodePen&quot; &gt;@CodePen&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/replit&quot; &gt;@replit&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/glitch&quot; &gt;@glitch&lt;/a&gt; which give you text editor and a place to run your code&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You&amp;#39;ll see some code samples embeded in the&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#39;ll be posting links to the code on these sites as I go along&lt;/p&gt;
&lt;h2&gt;2. Text Data&lt;/h2&gt;
&lt;p&gt;In a program, we can store different types of data (known as &amp;quot;data types&amp;quot;)&lt;/p&gt;
&lt;p&gt;When we store text we use a data type called &lt;code&gt;string&lt;/code&gt;. In JavaScript a string is just text surrounded in either double quotes, single quotes, or &lt;code&gt;`these things`&lt;/code&gt; (which are known as backticks):&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;i am text&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;i am also text&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`me too.`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`unlike the others,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  i can b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;multiple lines&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;lllooonnnggg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    and have random spaces`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;3. Variables&lt;/h2&gt;
&lt;p&gt;If we want to keep our data for use at a later stage we need to give it a name, otherwise how do we know what data we&amp;#39;re trying to use right? To give a piece of data (or text, in our case) a name we create a &lt;code&gt;variable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We create a variable using &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; along with a variable name and the data that we want to give the name to :&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt3?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// this code shouldn&amp;#39;t do anything if you run it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// we are just creating some variables&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; myText &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Hello World&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myOtherText&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Bye World&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;We use &lt;code&gt;let&lt;/code&gt; for data whose data may change and &lt;code&gt;const&lt;/code&gt; for data whose data won&amp;#39;t you can remember this like: &lt;code&gt;const = constant&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that it is also possible to use the keyword &lt;code&gt;var&lt;/code&gt; to create a variable. This is something that is left over from older versions of JavaScript and can have some effects that are better to just avoid (if you&amp;#39;re interested you can read &lt;a href=&quot;https://medium.com/@josephcardillo/the-difference-between-function-and-block-scope-in-JavaScript-4296b2322abe&quot; &gt;this article about how it impacts variable scope&lt;/a&gt; but it is a bit of a more challenging concept to understand)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When creating a variable, there are a few rules we need to follow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Variable names &lt;strong&gt;must not&lt;/strong&gt; contain spaces or stuff like &lt;code&gt;!@#%%^&amp;amp;\*()&lt;/code&gt;, underscores and dollar signs are okay though&lt;/li&gt;
&lt;li&gt;Variable names &lt;strong&gt;must not&lt;/strong&gt; be a word the language has set aside for something else. e.g &lt;code&gt;const&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Variable names &lt;strong&gt;must not&lt;/strong&gt; start with a number&lt;/li&gt;
&lt;li&gt;Variable names &lt;strong&gt;should be&lt;/strong&gt; descriptive. while names like &amp;quot;x&amp;quot; and &amp;quot;blah&amp;quot; are allowed, if they have no meaning in the context it&amp;#39;s better to opt for something people will understand&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. Printing Data&lt;/h2&gt;
&lt;p&gt;Languages have ways we can show data to a user (or programmer). In JavaScript this is the &amp;quot;console.log&amp;quot; function. We&amp;#39;ll discuss functions later on but for now know that when we give them data, and they do stuff&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt4?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print the data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Bob Smith&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//prints -&amp;gt; Bob Smith&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print a variable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jenny&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Jenny Smith&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(jenny) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// prints -&amp;gt; Jenny Smith&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;5. Numbers&lt;/h2&gt;
&lt;p&gt;Numbers are another type of data in JavaScript, to store a number we can just write the number. using numbers we can also do things like getting fat or running from the po-lice&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; is plus&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; is minus&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*&lt;/code&gt; is multiply&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt; is divide&lt;/li&gt;
&lt;/ol&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt5?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myWeight&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; food&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 50&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myNewWeight&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; myWeight &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; food&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myNewWeight) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; 250&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myWeightAfterRunnin&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; myWeight &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; myWeight &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myWeightAfterRunnin) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; 80&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;But, JavaScript lets us add do maths with anything. so maybe like - don&amp;#39;t do this:&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt5-1?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dontDoThis&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;pineapple&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dontDoThis) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; NaN (Not a Number)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;6. Arrays&lt;/h2&gt;
&lt;p&gt;Arrays are how we store a set of data. an array can have different data types in it, but usually, we want to be storing the same stuff in an array. we make an array by wrapping our items in &lt;code&gt;[ ]&lt;/code&gt; and separating each item with a comma (&lt;code&gt;,&lt;/code&gt;)&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt6?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myFriends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;i&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;don&amp;#39;t&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;have&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;any&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; thingsToRemember&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;uhmm&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;42&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;12&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;idk, i guess i forgot&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; multipleLines&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;arrays don&amp;#39;t have to be&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;on a single&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;line&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;If we want to get a specific element in an array we can use the variable name with the index (position) of the element. the index starts at 0. we will get &lt;code&gt;undefined&lt;/code&gt; (I&amp;#39;ll explain this in a bit) if we try to get a value at an index that does not exist&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt6-1?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;zeroeth index&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;first index&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;second index&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;third index&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; zeroeth index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; first index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; second index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; third index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// indexes that do not exist in our array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;7. Booleans&lt;/h2&gt;
&lt;p&gt;So far we&amp;#39;ve looked at strings and numbers, we have an even more basic data type called a boolean. a boolean is a value that can either be true or false. when creating a variable for a boolean we do not wrap the value in quotes&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt7?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; myTrueBool &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; myFalseBool &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myTrueBool)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myFalseBool)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;8. Complex Data&lt;/h2&gt;
&lt;p&gt;If we want to store data that are more complex than the ones we&amp;#39;ve seen above, we can make use of &amp;quot;objects&amp;quot;. use &lt;code&gt;{ }&lt;/code&gt; around our data to group more basic data. these use &lt;code&gt;keys&lt;/code&gt; as names for values in the object&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt8?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jenny&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  id: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;123&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Jenny&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  surname: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Smith&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  age: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;idk, can&amp;#39;t ask a woman that&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  favouriteBooks: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;To not kill a Mockingbird&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;Why are books so voilent, yoh&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// we can get specific values using their keys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jennyName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jenny.name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jennyBooks&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jenny.favouriteBooks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;9. Undefined and Null&lt;/h2&gt;
&lt;p&gt;the values &lt;code&gt;undefined&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt; have a special meaning.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;undefined&lt;/code&gt; is a representation for a variable that does not have a value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt; is a value of &amp;quot;nothing&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What&amp;#39;s wrong with chocolate? &lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;What&amp;#39;s a flobuir? &lt;code&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;10. Functions&lt;/h2&gt;
&lt;p&gt;Functions are a way we can group code for a specific set of instructions, usually with some end purpose. In JavaScript we define a function in one of two ways: using the word &lt;code&gt;function&lt;/code&gt; or with the &lt;code&gt;fat arrow syntax&lt;/code&gt;&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-pt10?lite=false&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// using the &amp;quot;function&amp;quot; keyword&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// this creates a variable called &amp;quot;myFunc1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; myFunc&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; stuff&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;I am Function&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(stuff)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// we can also create the variable using&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// &amp;quot;let&amp;quot; or &amp;quot;const&amp;quot; like we do for other variables&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; myLetFunc&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; stuff&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;I am another Function&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(stuff)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// fat arrow function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; myFatFunc&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Phat Funk&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// single line fat-arrow functions don&amp;#39;t need the {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; mySingleLineFunct&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;single line&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;To use a function we simply write the name of the function and then add &lt;code&gt;()&lt;/code&gt; at the end, provided the function doesn&amp;#39;t take any data (also known as &lt;code&gt;parameters&lt;/code&gt;)&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-10-1?lite=false&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sayHello&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// &amp;quot;call&amp;quot; the function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sayHello&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// prints -&amp;gt; Hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sayBye&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;BYEE&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// &amp;quot;call&amp;quot; the function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sayBye&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// prints -&amp;gt; BYEE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;Remember earlier I said that functions take data and do stuff? For us to give a function data we need to tell it what variables to store that data as when we call it. We do this by having the data in the &lt;code&gt;()&lt;/code&gt; when we create (or &amp;#39;declare&amp;#39;) our function&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-10-2?lite=false&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sayHello&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// use the function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sayHello&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Bob&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; Hello Bob&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sayBye&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Bye &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//use the function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Jenny&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sayBye&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(name) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; Bye Jenny&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;When computers are following our code they do so from the top down, so the first line is handled by the computer before the second. the second before the third, etc. functions are a way for us to reuse code that was written on a line higher up in our code. You may notice that we use the variable &lt;code&gt;name&lt;/code&gt; in a lot of different places above. this uses &lt;code&gt;scope&lt;/code&gt; and broadly means any variable name created in a function (or pretty much anywhere between &lt;code&gt;{ }&lt;/code&gt;) is only available within that section&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Scope complicated, you can read more about it &lt;a href=&quot;https://scotch.io/tutorials/understanding-scope-in-JavaScript&quot; &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Functions can also take multiple parameters, this is done by listing the parameters between the () and separating them by commas. the order that we list them when we create our function is the same as the order we need to put them when using the function&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-10-3?lite=false&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sayBye&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;firstName&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;lastName&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Bye &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; firstName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; lastName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// use the function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jennyName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Jenny&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; jennySurname&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Smith&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sayBye&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(jennyName, jennySurname) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; Bye Jenny Smith&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;Functions are also able to give us back a value after doing some stuff. They do this by using the &lt;code&gt;return&lt;/code&gt; keyword which tells it what to give back. A function stops processing when it sees the keyword &lt;code&gt;return&lt;/code&gt; - anything after it in a function is ignored&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/twitter-10-4?lite=false&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;details&gt;
  &lt;summary&gt;View Code&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; addNumbers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;num1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;num2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; num1 &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; num2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; mySum&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; addNumbers&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(mySum) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// print -&amp;gt; 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&amp;#39;s it for now, I&amp;#39;ll definitely be updating this post/series as things are added&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Custom Attributes in C# Web Controllers</title><link>https://nabeelvalley.co.za/blog/2020/17-12/csharp-webapi-custom-attributes.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/17-12/csharp-webapi-custom-attributes.html</guid><description>Modify controller behaviour using Attributes</description><pubDate>Thu, 17 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Custom Attributes in C# Web Controllers&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Implementing an attribute for a WebAPI or class in C# can help to reduce duplication and centralize parts of the application logic. This could be used for a variety of tasks such as logging information when methods are called as well as managinng authorization&lt;/p&gt;
&lt;p&gt;In this post I&amp;#39;m going to cover the following:&lt;/p&gt;
&lt;h2&gt;Attribute Types and Execution Order&lt;/h2&gt;
&lt;p&gt;There are a few different attribute types that we can handle on a WebAPI that provide us with the ability to wrap some functionality around our endpoints, below are some of the common attributes that we can implement and the order in which they execute (&lt;a href=&quot;https://stackoverflow.com/questions/19249511/difference-between-iactionfilter-and-iauthorizationfilter&quot; &gt;StackOverflow&lt;/a&gt;)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Authorization - &lt;code&gt;IAuthorizationFilter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Action - &lt;code&gt;IActionFilter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Result - &lt;code&gt;IResultFilter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Exception - &lt;code&gt;IExceptionFilter&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;IActionFilter&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;IActionFilter&lt;/code&gt; executes before and after a method is executed and contains two different methods for doing this, namely the &lt;code&gt;OnActionExecuting&lt;/code&gt; and &lt;code&gt;OnActionExecuted&lt;/code&gt; methods respectively. A basic implemtation of &lt;code&gt;IActionFilter&lt;/code&gt; would look like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSharpAttributes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attributes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; LogStatusAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;IActionFilter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; LogStatusAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Attribute Initialized&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OnActionExecuting&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ActionExecutingContext&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;OnActionExecuting&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OnActionExecuted&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ActionExecutedContext&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;OnActionExecuted&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This can then be implemented on a controller method with a &lt;code&gt;[LogStatus]&lt;/code&gt; attribute:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;LogStatus&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;HttpGet&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;WeatherForecast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Executing Get&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The order of logging which we see will be as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnActionExecuting&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnActionExecuted&lt;/code&gt; when the controller is done executing&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;IAuthorizationFilter&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;IAuthorizationFilter&lt;/code&gt; executes as the first filter on a controller&amp;#39;s method call&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSharpAttributes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attributes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CustomAuthorizeAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;IAuthorizationFilter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; CustomAuthorizeAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Attribute Initialized&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OnAuthorization&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AuthorizationFilterContext&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;OnAuthorization&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This can then be implemented on a controller method with a &lt;code&gt;[CustomAuthorize]&lt;/code&gt; attribute:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;CustomAuthorize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;HttpGet&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;WeatherForecast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Executing Get&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The order of logging which we see will be as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OnAuthorization&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Modify Response Data&lt;/h2&gt;
&lt;p&gt;An attribute&amp;#39;s &lt;code&gt;context&lt;/code&gt; parameter gives us ways by which we can access the &lt;code&gt;HttpContext&lt;/code&gt; as well as set the result of a method call so that it can be handled down the line. For example, we can implement our CustomAuthorize attribute with the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OnAuthorization&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AuthorizationFilterContext&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;context.HttpContext.Request.Headers.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;ContainsKey&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;X-Custom-Auth&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    context.Result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UnauthorizedResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Attribute Called&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will mean that if we set the &lt;code&gt;context.Result&lt;/code&gt; in our method then the controller will not be executed and the endpoint will return the &lt;code&gt;UnauthorizedResult&lt;/code&gt; early. You can also see that we&amp;#39;re able to access things like the &lt;code&gt;HttpContext&lt;/code&gt; which makes it easy for us to view the request/response data and do things based on that&lt;/p&gt;
&lt;h2&gt;Attribute on a Class&lt;/h2&gt;
&lt;p&gt;Note that it&amp;#39;s also possible to apply the above to each method in a class by adding the attribute at the top of the class declaration:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ApiController&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;LogStatus&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;[controller]&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WeatherForecastController&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ControllerBase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Attributes with Input Parameters&lt;/h2&gt;
&lt;p&gt;We are also able to create attributes that enable the consumer to modify their behaviour by taking input parameters to the constructor, we can update our &lt;code&gt;LogStatus&lt;/code&gt; attribute to do something like add a prefix before all logs:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSharpAttributes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attributes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; LogStatusAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;IActionFilter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; _prefix&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; LogStatusAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; prefix&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      _prefix &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; prefix;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Attribute Initialized&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OnActionExecuted&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ActionExecutedContext&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(_prefix &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;OnActionExecuted&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OnActionExecuting&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ActionExecutingContext&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(_prefix &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;OnActionExecuting&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then, applying to our controller method like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;LogStatus&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;WeatherController-Get:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;HttpGet&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;WeatherForecast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Executing Get&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So the new output will look like so:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherForecast-Get:OnActionExecuting&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherForecast-Get:OnActionExecuted&lt;/code&gt; when the controller is done executing&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Attribute Setting at Class and Method Level&lt;/h2&gt;
&lt;p&gt;Since an attribute can be implemented at a class and method level it&amp;#39;s useful for us to be able to implement it at a class and the override the behaviour or add behaviour for a specific method&lt;/p&gt;
&lt;p&gt;We can do this by setting the attribute inheritence to &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Updating out &lt;code&gt;LogStatusAttribute&lt;/code&gt; we can add the &lt;code&gt;AttributeUsage&lt;/code&gt; Attribute as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSharpAttributes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attributes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AttributeUsage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(AttributeTargets.All, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Inherited&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; LogStatusAttribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Attribute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;IActionFilter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This means that we can independently apply the attribute at class and method levels, so now our controller can look something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;cs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSharpAttributes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Controllers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ApiController&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;[controller]&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;LogStatus&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;WeatherForecast:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WeatherForecastController&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ControllerBase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;LogStatus&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Get:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;HttpGet&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;WeatherForecast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Executing Get&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which will output the logs as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Attribute Initialized&lt;/code&gt; when the controller is instantiated&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherForecast:OnActionExecuting&lt;/code&gt; when the class is called&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Get:OnActionExecuting&lt;/code&gt; when the controller is called&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Executing Get&lt;/code&gt; when the controller is executed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Get:OnActionExecuted&lt;/code&gt; when the controller is done executing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WeatherForecast:OnActionExecuted&lt;/code&gt; when the class is done executing&lt;/li&gt;
&lt;/ol&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>The Gatsby Migration, pt.1 - Setting the Scene</title><link>https://nabeelvalley.co.za/blog/2020/21-01/gatsby-migration-1.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/21-01/gatsby-migration-1.html</guid><description>Building a basic React site with basic dynamic data loading</description><pubDate>Tue, 21 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;The Gatsby Migration, pt.1 - Setting the Scene&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Lately I&amp;#39;ve been a little concerned with my current SPA approach on my personal site as well as a few others. More specifically the high initial load time due to the calls to the backend to retrieve content&lt;/p&gt;
&lt;p&gt;With the aim of solving this problem I&amp;#39;ve spent a lot of time looking at and playing with Static Site Generators.Foreword: they&amp;#39;re all a lot more complicated than one would think&lt;/p&gt;
&lt;p&gt;So for a static site the &amp;quot;static&amp;quot; content only changes so often, based on this we can generate page content with the data we&amp;#39;re planning to load in - that&amp;#39;s what we&amp;#39;re going to try to do&lt;/p&gt;
&lt;p&gt;Now we&amp;#39;ll be starting off with a React app generated with &lt;code&gt;create-react-app&lt;/code&gt; so that we can have a starting point for our Gatsby site as well as understanding how we can approach some of the challenges when switching over to a site generator like Gatsby&lt;/p&gt;
&lt;p&gt;For the sake of completeness, this series will be broken into four posts covering the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Creating the initial React App&lt;/strong&gt; (This post)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2020/01-02/gatsby-migration-2&quot; &gt;Rendering the &amp;quot;Dumb&amp;quot; pages with Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2020/15-03/gatsby-migration-3&quot; &gt;Rendering the &amp;quot;Smart&amp;quot; page with Gatsby&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;The React App&lt;/h2&gt;
&lt;p&gt;First we&amp;#39;re going to be starting off with a new React app that we will work on changing into a Gatsby one parts &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt;, we&amp;#39;ll then focus on using plugins to enhance our content in &lt;code&gt;4&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For this part we&amp;#39;ll build a basic React app that has the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Two &amp;quot;hard-coded&amp;quot; pages and a 404 page&lt;/li&gt;
&lt;li&gt;A dynamic page with an API call to retrieve data&lt;/li&gt;
&lt;li&gt;Overall app layout with child routes for &lt;code&gt;1&lt;/code&gt; - &lt;code&gt;3&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To get started, we&amp;#39;ll create a fresh React App:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;npx create-react-app gatsby-to-be&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And add the &lt;code&gt;react-router&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;yarn add react-router-dom&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Running this command should set up the application, if you don&amp;#39;t know much about React I&amp;#39;d suggest taking a look at &lt;a href=&quot;https://create-react-app.dev/docs/getting-started&quot; &gt;the documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next &lt;code&gt;cd gatsby-to-be&lt;/code&gt; and run &lt;code&gt;yarn start&lt;/code&gt;, you should be able to visit the application in your browser at &lt;code&gt;http://localhost:3000/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Looking at the generated files we have a &lt;code&gt;public&lt;/code&gt; directory with some icons, an &lt;code&gt;index.html&lt;/code&gt; file into which our React application will run once built, and a &lt;code&gt;src&lt;/code&gt; directory that has the application code. The &lt;code&gt;index.js&lt;/code&gt; file is what loads the application into the DOM and the &lt;code&gt;App.js&lt;/code&gt; file which is the main component for our application&lt;/p&gt;
&lt;h2&gt;Hard Coded Pages&lt;/h2&gt;
&lt;p&gt;We will create the following three hard-coded pages in the &lt;code&gt;src/pages&lt;/code&gt; directory&lt;/p&gt;
&lt;p&gt;These pages are just React components that we will assign Routes to.&lt;/p&gt;
&lt;p&gt;The pages we are using are known as &lt;code&gt;functional&lt;/code&gt; components because they are javascript functions that return JSX&lt;/p&gt;
&lt;p&gt;If we intend to use JSX in a file we need to ensure that we import &lt;code&gt;React&lt;/code&gt;. The other component we are importing is the &lt;code&gt;Link&lt;/code&gt; component which is a lot like a normal HTML &lt;code&gt;a&lt;/code&gt; tag but with some special functionality to make the client-side navigation work&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Blog.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Link } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react-router-dom&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Blog&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Blog&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Blog&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is the Blog page&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/post-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Post 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/post-2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Post 2&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Blog&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Additionally we have the &lt;code&gt;Home.js&lt;/code&gt; and &lt;code&gt;NotFound.js&lt;/code&gt; files which are similar to the &lt;code&gt;Blog.js&lt;/code&gt; file we created&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Home&lt;/summary&gt;&lt;p&gt;&lt;code&gt;Home.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Home&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Home&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Home&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is the Home page&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;details&gt;
&lt;summary&gt;Not Found&lt;/summary&gt;&lt;p&gt;&lt;code&gt;NotFound.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; NotFound&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;NotFound&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;404&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Page Not Found&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; NotFound&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;Dynamic Post Page&lt;/h2&gt;
&lt;p&gt;Next up we&amp;#39;ll create a component that can render out content for a blog post. This will consist of a few &lt;code&gt;hooks&lt;/code&gt; which are react functions that we can use to sort of control the data in a function&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Post&lt;/code&gt; component will:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Display a loading indicator initially&lt;/li&gt;
&lt;li&gt;Figure out what post we&amp;#39;re trying to render based on the URL&lt;/li&gt;
&lt;li&gt;Retrieve a JSON file from the &lt;code&gt;public&lt;/code&gt; directory based&lt;/li&gt;
&lt;li&gt;Set the component state after reading the file&lt;/li&gt;
&lt;li&gt;Display the content from the file in a JSX template&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;useState&lt;/code&gt; hook is used to initialize the state the component, in this case using the &lt;code&gt;hasError&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; variables, as well as providing the functions necessary for updating those in the form of &lt;code&gt;setHasError&lt;/code&gt; and &lt;code&gt;setData&lt;/code&gt; respectively&lt;/p&gt;
&lt;p&gt;We use &lt;code&gt;fetch&lt;/code&gt; in the &lt;code&gt;useEffect&lt;/code&gt; hook to retrieve the data from the &lt;code&gt;public&lt;/code&gt; directory. The &lt;code&gt;useEffect&lt;/code&gt; hook allows us to pass a function that will be called to update side effects. The second input, in our case &lt;code&gt;[]&lt;/code&gt; is the array of objects that, when are changed, we want the hook to run - since we only want it to run once and don&amp;#39;t care about any other state changes we pass in an empty array for this value&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Post.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React, { useEffect, useState } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Post&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; slug&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; match.params.slug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;hasError&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;setHasError&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; useState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;setData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; useState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;null&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  useEffect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fetchData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; res&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fetch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`/posts/${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;slug&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.json`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;json&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        setData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(json)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(error.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        setHasError&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    fetchData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }, [])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Post&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        This is the &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;slug&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;code&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; page&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data.title&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data.body&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data.image&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; hasError &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Error&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;hasError&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Loading .. &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      )&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Post&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above component we&amp;#39;re making use of the following pattern to decide what to render conditionally:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the data is loaded then show the data&lt;/li&gt;
&lt;li&gt;Else if there is an error then show the error data&lt;/li&gt;
&lt;li&gt;Otherwise show a loading message&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The way we are rendering the &lt;code&gt;Post&lt;/code&gt; component with a parameter for &lt;code&gt;match&lt;/code&gt;. The &lt;code&gt;match&lt;/code&gt; parameter will be passed in as a &lt;code&gt;prop&lt;/code&gt; from the &lt;code&gt;Router&lt;/code&gt; that we will configure next, this allows us to use the &lt;code&gt;slug&lt;/code&gt; from the URL to retrieve the content for the page&lt;/p&gt;
&lt;p&gt;The two data files we have to pull content from in the &lt;code&gt;public/posts&lt;/code&gt; directory are &lt;code&gt;post-1.json&lt;/code&gt; and &lt;code&gt;post-2.json&lt;/code&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Post 1 - JSON&lt;/summary&gt;&lt;p&gt;&lt;code&gt;post-1.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;title&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Post 1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;body&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world, how are you&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/posts/1.jpg&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;details&gt;
&lt;summary&gt;Post 2 - JSON&lt;/summary&gt;&lt;p&gt;&lt;code&gt;post-2.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;title&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Post 2&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;body&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world, I am fine&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/posts/2.jpg&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The images &lt;code&gt;posts/1.jpg&lt;/code&gt; and &lt;code&gt;posts/2.jpg&lt;/code&gt; can also just be any images in that directory&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/details&gt;&lt;h2&gt;App Layout and Routes&lt;/h2&gt;
&lt;p&gt;Lastly, we&amp;#39;ll specify our application layout with the relevant routes in the &lt;code&gt;App.js&lt;/code&gt; file, referencing the components we have created, we do this using the &lt;code&gt;BrowserRouter&lt;/code&gt;. When we switch the project over to a Gatsby one, the &lt;code&gt;App.js&lt;/code&gt; file will be converted into our &lt;code&gt;Layout&lt;/code&gt; component to wrap our different pages&lt;/p&gt;
&lt;p&gt;We use the &lt;code&gt;Router&lt;/code&gt; component and the page inside of it, this essentially handles Routing via the &lt;code&gt;Link&lt;/code&gt; components. Next we have a &lt;code&gt;div&lt;/code&gt; as a wrapper for our component as well as a &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;nav&lt;/code&gt;, and &lt;code&gt;main&lt;/code&gt; tags to organise the page&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Route&lt;/code&gt; component takes in the component that we would like to display for a given route, and the &lt;code&gt;Switch&lt;/code&gt; helps us to ensure that only route is actively being fisplayed at a time. The &lt;code&gt;Switch&lt;/code&gt; will navigate from the first to last &lt;code&gt;Route&lt;/code&gt; and render the first one that matches the given &lt;code&gt;path&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Fow now, our &lt;code&gt;App.js&lt;/code&gt; file is as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./App.css&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { BrowserRouter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Router, Link, Switch, Route } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react-router-dom&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Home &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./pages/Home&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Blog &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./pages/Blog&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Post &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./pages/Post&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; NotFound &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./pages/NotFound&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; App&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Router&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; className&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;App&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;header&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;nav&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;My Website Title&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Home&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Blog&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;nav&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;header&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; exact&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; component&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Home&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; exact&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; component&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Blog&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; exact&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/blog/:slug&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; component&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Post&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/*&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; component&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;NotFound&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Route&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Router&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above component we can see that where we are rendering the &lt;code&gt;Post&lt;/code&gt; component we have a parameter in the route called &lt;code&gt;slug&lt;/code&gt;, this parameter will be passed in to the &lt;code&gt;Post&lt;/code&gt; component as part of the &lt;code&gt;match&lt;/code&gt; object&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;We have built a fairly simple application that makes use of both static and data-based pages, we have also tied all of these together using the &lt;code&gt;App&lt;/code&gt; component and a &lt;code&gt;Router&lt;/code&gt; with the following routes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt; which will render the &lt;code&gt;Home&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/blog&lt;/code&gt; which will render the &lt;code&gt;Blog&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/blog/:slug&lt;/code&gt; which will render the &lt;code&gt;Post&lt;/code&gt; component and retrieve the data based on the given &lt;code&gt;slug&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/*&lt;/code&gt; which will match any other routes and render the &lt;code&gt;NotFound&lt;/code&gt; component&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the next post we&amp;#39;re going to look at how to take what we have so far and transform this application into a Gatsby one, but for now it may be useful to think about what kind of steps we may need to take if we&amp;#39;d like to make this a static website based on the way our current routes work&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Mongo DB in Docker</title><link>https://nabeelvalley.co.za/blog/2020/22-09/mongo-db-in-docker.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/22-09/mongo-db-in-docker.html</guid><description>Run a MongoDB Instance with Docker or Docker Compose</description><pubDate>Tue, 22 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Mongo DB in Docker&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Considerations&lt;/h2&gt;
&lt;p&gt;To run MongDB in a Docker Container there are a few things to take note of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You may need to configure auth&lt;/li&gt;
&lt;li&gt;Volume storage to be set up&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;From Terminal&lt;/h2&gt;
&lt;p&gt;To run a Docker container using a single command in the terminal you can run the following command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;docker&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -d&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -p&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; 27017:27017&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can also specify additional information like the volumes you would like to use using flags when running:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;docker&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -d&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -p&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; 27017:27017&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;From Compose&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;More info can be found &lt;a href=&quot;https://medium.com/faun/managing-mongodb-on-docker-with-docker-compose-26bf8a0bbae3&quot; &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can also run a MongoDB Container with Compose which may be a bit easier:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;yml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;version&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;3.3&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;services&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  # mongonode0:27017&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  mongo0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    image&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;mongo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    hostname&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;mongo0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    container_name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;mongo0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    restart&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;always&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    ports&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      - &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;37000:27017&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    volumes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      - &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;./mongo0-data:/data/db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    environment&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      MONGO_INITDB_ROOT_USERNAME&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;password&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Split an Array into Segments</title><link>https://nabeelvalley.co.za/blog/2020/23-09/split-an-array-into-segments.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/23-09/split-an-array-into-segments.html</guid><description>Distribute elements of an array over a fixed number of segments</description><pubDate>Wed, 23 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Split an Array into Segments&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;It can sometimes be useful to split an array into a separated set of rows or columns, such as when trying to separate elements into buckets while maintaing order.&lt;/p&gt;
&lt;p&gt;For example, given the following &lt;code&gt;input&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; input&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;6&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;7&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;9&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;With the desired &lt;code&gt;output&lt;/code&gt; array as follows, in which we split elements into different rows, while maintaing a top-down/left-right ordering:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; output&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;7&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;6&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;9&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can accomplish this using a function like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;arr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;segments&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(segments)].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;_&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;outerPos&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    input.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;filter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;el&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;innerPos&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; innerPos &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; segments &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; outerPos)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which can then be used with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; rows&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; transformedData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input, rows)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Generate data for a Postman request</title><link>https://nabeelvalley.co.za/blog/2020/24-11/generate-postman-data.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/24-11/generate-postman-data.html</guid><description>Using Pre-Request Scripts and Environment variables to generate data in Postman</description><pubDate>Tue, 24 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Generate data for a Postman request&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When making requests with Postman to test an API it is often useful to have generated data, for example when creating users in a backend system you may want the ability to get custom user data&lt;/p&gt;
&lt;p&gt;The method we will use to do this is by setting Postman environment variables in the Pre-request Script of a Postman request&lt;/p&gt;
&lt;p&gt;Firstly, we can write some basic logging in the Pre-request script section on Postman and view the result in the Postman console:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Nabeel&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`Hello ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Additionally, postman gives us some functions to set and get environment variables, so we can set the name as an environment variable like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Nabeel&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;pm.environment.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;set&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And log it like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(pm.environment.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Aditionally, we can make HTTP Requests using &lt;code&gt;pm.sendRequest&lt;/code&gt; which then takes a callback for what we want to do after the request, we can use the &lt;code&gt;randomuser&lt;/code&gt; api to get a user:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;pm.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sendRequest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;https://randomuser.me/api/&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;err&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; apiResponse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;json&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do more stuff&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using this method, we can get some random user data and set it in the environment variables as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;pm.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sendRequest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;https://randomuser.me/api/&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;err&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; apiResponse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;json&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; apiResponse.results[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.email&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; firstName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.name.first&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; lastName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.name.last&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  pm.environment.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;set&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, email)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  pm.environment.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;set&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;firstName&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, firstName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  pm.environment.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;set&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lastName&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, lastName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then use this in our request body using Postman&amp;#39;s &lt;code&gt;{\{}\}&lt;/code&gt; syntax. If we were making a JSON request, our body would look something like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;POST: https://my-api.com/users&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;email&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;{{email}}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;firstName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;{{firstName}}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;lastName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;{{lastName}}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Postman will then populate the slots from the environment variables that we set automatically when making the request&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Code in a Container</title><link>https://nabeelvalley.co.za/blog/2020/25-07/developing-in-a-container-vscode.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/25-07/developing-in-a-container-vscode.html</guid><description>Using a Docker Container as a development container using the Visual Studio Code Remote-Containers Extension</description><pubDate>Sat, 25 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Code in a Container&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Recently I&amp;#39;d started using Visual Studio Code&amp;#39;s &lt;em&gt;Remote Containers&lt;/em&gt; functionality for development and it&amp;#39;s been really useful&lt;/p&gt;
&lt;p&gt;The Remote Containers extension allows us to write code and develop applications within a virtualized environment that makes it easier for us to manage our development environment as well as more closely resemble our target deployment environment (if we&amp;#39;re deploying to Docker or Kubernetes)&lt;/p&gt;
&lt;p&gt;In this post, I&amp;#39;ll take a look at what a Docker container is, why we would want to use one as a development environment, and how we can go about setting one up for VSCode&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;If you intend to follow along with this post you&amp;#39;ll need to have the following installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Windows or Mac OS version capable of running Docker Desktop&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/desktop/#download-and-install&quot; &gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot; &gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers&quot; &gt;Visual Studio Code&amp;#39;s Remote Containers Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker&quot; &gt;Visual Studio Code&amp;#39;s Docker Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Some familiarity with using the command line&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Docker Containers&lt;/h2&gt;
&lt;p&gt;A Container, in this context, is a simple virtual machine that contains the code required to run an application with all its dependencies&lt;/p&gt;
&lt;p&gt;A Docker container is built from a &lt;code&gt;docker image&lt;/code&gt; and run by the &lt;code&gt;docker&lt;/code&gt; command. I&amp;#39;ll explain these as we go along&lt;/p&gt;
&lt;p&gt;To check that Docker is installed correctly on your machine run the following command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;docker run hello-world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If your install is working correctly you should see something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Unable to find image &amp;#39;hello-world:latest&amp;#39; locally&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;latest: Pulling from library/hello-world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;0e03bdcc26d7: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Digest: sha256:49a1c8800c94df04e9658809b006fd8a686cab8028d33cfba2cc049724254202&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Status: Downloaded newer image for hello-world:latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Hello from Docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Docker Images&lt;/h2&gt;
&lt;p&gt;Docker images are typically used to run applications in a production-type environment, every Docker container we run needs to be based on an image, every running container is like an instance of an image - similar to how objects are an instance of a class&lt;/p&gt;
&lt;p&gt;An image states what our container will need to be made of, what it depends on, and how it runs. We define how docker should build our image in a &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#39;re going to go through some of the basics of Docker Images and Docker as would typically be done when creating a container to be run in production before we get into development containers so you&amp;#39;ve got an understanding of how this all works&lt;/p&gt;
&lt;p&gt;To get started create a new folder and open it from Visual Studio Code and do the following:&lt;/p&gt;
&lt;h3&gt;Create an Application&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ll need a simple &amp;quot;hello-world&amp;quot; web server using Node.js, for the sake of example. You can, however, use any language (or Languages) you want when creating an application to run within Docker. You do not need to have any dependencies for the specific application or language installed on your computer, we will handle this using Docker&lt;/p&gt;
&lt;p&gt;For our purpose, create a file called &lt;code&gt;index.js&lt;/code&gt; with the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; http&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; requestListener&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;req&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;writeHead&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;200&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  res.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; serverListeningCallback&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Server started&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; server&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; http.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createServer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(requestListener)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;server.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;listen&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8080&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, serverListeningCallback)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can see in the above on the last line that the application will listen on port 8080, just keep this in mind&lt;/p&gt;
&lt;p&gt;We don&amp;#39;t need to run this file as yet, but if we want, we can run this with the following command from our working directory:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; app.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At this point our working directory should look like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;working-directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ index.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Create a Dockerfile&lt;/h3&gt;
&lt;p&gt;There are a few steps that are the same for most &lt;code&gt;Dockerfile&lt;/code&gt;s you&amp;#39;ll be building:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A Base Image that your container/image should use, in our case &lt;code&gt;node:12&lt;/code&gt;, which has &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; preinstalled&lt;/li&gt;
&lt;li&gt;Copy all the code in the current (&lt;code&gt;.&lt;/code&gt;) directory&lt;/li&gt;
&lt;li&gt;Define your runtime port/ports (in the case of a web application)&lt;/li&gt;
&lt;li&gt;The command that will be run to start the application&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Any line starting with a &lt;code&gt;#&lt;/code&gt; is a comment, Docker will ignore these&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;dockerfile&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## step 1 - FROM baseImage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; node:12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## step 2 - COPY source destination&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;COPY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; . .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## step 3 - EXPOSE port&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;EXPOSE&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; 8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## step 4 - CMD stratupCommandArray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;CMD&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;app.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At this point our working directory should look like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;working-directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ index.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ Dockerfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can build our image, based on the &lt;code&gt;Dockerfile&lt;/code&gt; using the following &lt;code&gt;docker&lt;/code&gt; command:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note the &lt;code&gt;.&lt;/code&gt; at the end of the command&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;docker build -t my-docker-app .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above command can be broken down as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;docker build&lt;/code&gt; the command from the Docker CLI to build an image&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-t my-docker-app&lt;/code&gt; says what we want our image to be called, in the above &lt;code&gt;my-docker-app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt; which is the directory in which the &lt;code&gt;Dockerfile&lt;/code&gt; is located, in our case our current directory&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can then run the image we just built like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;docker run -p 8080:8080 my-docker-app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;docker run&lt;/code&gt; is the command from the &lt;code&gt;Docker CLI&lt;/code&gt; to run a container&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p 8080:8080&lt;/code&gt; is our port mapping, it is ordered as &lt;code&gt;HOST_PORT:CONTAINER_PORT&lt;/code&gt; and allows us to say which port on our host we want to map to our container, the container port is the same port that our app listens on and is &lt;code&gt;EXPOSE&lt;/code&gt;d in the &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;my-docker-app&lt;/code&gt; is the image tag we would like to run&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Each time we change the app files for a container like above we need to rebuild the container before running, and that normally making changes to files during the image build or container run will not modify the original files on our computer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now that the application is running on port &lt;code&gt;8080&lt;/code&gt; you can open &lt;code&gt;http://localhost:8080&lt;/code&gt; in your browser and you should see your &lt;code&gt;Hello World&lt;/code&gt; app running&lt;/p&gt;
&lt;p&gt;When you&amp;#39;re done with that you can go back to the terminal where the container was started and use &lt;code&gt;ctrl + c&lt;/code&gt; to stop the container&lt;/p&gt;
&lt;p&gt;If you&amp;#39;ve never used Docker before and have got everything running this far, congratulations! If you&amp;#39;ve got any questions you can comment below or hit me up on &lt;a href=&quot;https://twitter.com/not_nabeel&quot; &gt;Twitter @not_nabeel&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Moving swiftly along&lt;/p&gt;
&lt;h2&gt;Development Containers&lt;/h2&gt;
&lt;p&gt;So now that we understand a bit about containers and how we can go about using them in production, we&amp;#39;ll look at why we may want to use them as a development environment&lt;/p&gt;
&lt;h3&gt;Why Develop in a Container&lt;/h3&gt;
&lt;p&gt;As developers, we are far too familiar with the &amp;quot;it runs on my machine&amp;quot; dilemma. Development environments can be wildly inconsistent between different developers or different operating systems, and ensuring that our development code runs easily on everyone&amp;#39;s computer can be challenging&lt;/p&gt;
&lt;p&gt;Containers can help us to explicitly define our development environment, our application dependencies, what networking relationships, and (potentially) what other sibling applications need to be running in development, like databases, or other application tiers&lt;/p&gt;
&lt;p&gt;Visual Studio Code can help transport us into a container so that we work on our application in a well-defined environment, not just run our application within one while reducing the overall number of things we need to have installed on our computer&lt;/p&gt;
&lt;h3&gt;How to Develop in a Container&lt;/h3&gt;
&lt;p&gt;To develop in a Container using Visual Studio Code we will need to have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/desktop/#download-and-install&quot; &gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot; &gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers&quot; &gt;Visual Studio Code&amp;#39;s Remote Containers Extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;What&amp;#39;s important to note is that we don&amp;#39;t need any of our application&amp;#39;s runtime or development dependencies installed, like Node.js, these will all be handled by VSCode within our container&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To configure our project for running in a container we need to first open the project folder (the folder we used previously) in Visual Studio Code&lt;/p&gt;
&lt;h4&gt;Use an Existing Dockerfile&lt;/h4&gt;
&lt;p&gt;Once open use the keyboard shortcut &lt;code&gt;ctrl + shift + p&lt;/code&gt; to open the Command Palette and search for &lt;code&gt;Remote-Containers: Add Development Container Configuration Files&lt;/code&gt; and click &lt;code&gt;enter&lt;/code&gt;, you will then have an option to use the existing Dockerfile &lt;code&gt;from Dockerfile&lt;/code&gt; which will generate a &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file&lt;/p&gt;
&lt;p&gt;At this point our working directory should look like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;working-directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ .devcontainer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|   |__ devcontainer.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ index.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ Dockerfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file that was created will contain the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file&amp;#39;s README at:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// https://github.com/microsoft/vscode-dev-containers/tree/v0.128.0/containers/docker-existing-dockerfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Existing Dockerfile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Sets the run context to one level up instead of the .devcontainer folder.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;context&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;..&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Update the &amp;#39;dockerFile&amp;#39; property if you aren&amp;#39;t using the standard &amp;#39;Dockerfile&amp;#39; filename.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;dockerFile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;..&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\\&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Dockerfile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Set *default* container specific settings.json values on container create.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;settings&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;terminal.integrated.shell.linux&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Add the IDs of extensions you want installed when the container is created.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;extensions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above file is the configuration for our development container, we can also allow VSCode to generate a Dockerfile which we&amp;#39;ll look at later in the post&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll stick to our simple &lt;code&gt;Dockerfile&lt;/code&gt; for this post, but if you&amp;#39;ve got a different &lt;code&gt;Dockerfile&lt;/code&gt; when running your application in Production and Development then you may need a different file in the &lt;code&gt;dockerFile&lt;/code&gt; property below&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve got a starting point we can add a little to our configuration so that everything is just right:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change the &lt;code&gt;name&lt;/code&gt; property to name our workspace (purely aesthetic)&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;forwardPorts&lt;/code&gt; property to expose our application port to our localhost network, be sure to add the &lt;code&gt;,&lt;/code&gt; after &lt;code&gt;&amp;quot;extensions&amp;quot;:[]&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once we make the above changes we should have this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;My Workspace&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Sets the run context to one level up instead of the .devcontainer folder.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;context&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;..&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Update the &amp;#39;dockerFile&amp;#39; property if you aren&amp;#39;t using the standard &amp;#39;Dockerfile&amp;#39; filename.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;dockerFile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;..&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\\&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Dockerfile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Set *default* container specific settings.json values on container create.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;settings&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;terminal.integrated.shell.linux&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Add the IDs of extensions you want installed when the container is created.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;extensions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Use &amp;#39;forwardPorts&amp;#39; to make a list of ports inside the container available locally.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;forwardPorts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we&amp;#39;ve configured our build container, use &lt;code&gt;ctrl + shift + p&lt;/code&gt; to open the Command Palette again and search for &lt;code&gt;Remote-Containers: Reopen in Container&lt;/code&gt; and click &lt;code&gt;enter&lt;/code&gt; which will build the container and set up an image with the following setup for us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linked ports as defined in the &lt;code&gt;forwardPorts&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;Configure a VSCode development server inside the container so our editor can link to it&lt;/li&gt;
&lt;li&gt;Mount our system&amp;#39;s file directory into the container so we can edit our files&lt;/li&gt;
&lt;li&gt;Does not run the &lt;code&gt;CMD&lt;/code&gt; command from our &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Open a VSCode window linked to the container so we can start working with our code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you&amp;#39;re in the container you can edit your files and run it by doing the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;ctrl + shift + p&lt;/code&gt; and then search for &lt;code&gt;Terminal: Create new Integrated Terminal&lt;/code&gt; and click &lt;code&gt;enter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;node app.js&lt;/code&gt; into the new Terminal window and click &lt;code&gt;enter&lt;/code&gt; to run our app.js file&lt;/li&gt;
&lt;li&gt;Navigate to &lt;code&gt;http://localhost:8080&lt;/code&gt; in your browser to view your running app&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At this point we&amp;#39;ve created a container to use as a development file and run our application, you can stop the application with &lt;code&gt;ctrl + c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can switch from developing in a container back to your local environment with &lt;code&gt;ctrl + shift + p&lt;/code&gt; and searching for &lt;code&gt;Remote-Containers: Reopen locally&lt;/code&gt; and clicking &lt;code&gt;enter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;re back on our local environment (and not docker) we can look at the other way we can set up our project for VSCode&lt;/p&gt;
&lt;h4&gt;Using a Preconfigured Dockerfile&lt;/h4&gt;
&lt;p&gt;Visual Studio Code&amp;#39;s Remote Containers Extension provides some pre-configured &lt;code&gt;Dockerfile&lt;/code&gt;s for common application or application framework types. One of the available preconfigured &lt;code&gt;Dockerfile&lt;/code&gt;s is for working on Node.js applications&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The preconfigured files usually just provide a starting point for applications and often you will need to modify these to suit your application, we don&amp;#39;t need this for the application we&amp;#39;re working on however&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To redefine our Docker development config, let&amp;#39;s delete the &lt;code&gt;.devcontainer&lt;/code&gt; directory in our application and regenerate this&lt;/p&gt;
&lt;p&gt;We can regenerate the files needed with &lt;code&gt;ctrl + shift + p&lt;/code&gt;, and searching for &lt;code&gt;Remote-Containers: Add Development Container Configuration Files&lt;/code&gt; again, clicking &lt;code&gt;enter&lt;/code&gt; and then selecting the &lt;code&gt;From a predefined configuration definition&lt;/code&gt; option, and then selecting &lt;code&gt;Node.js 12&lt;/code&gt;, this should now create a &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file as well as a new &lt;code&gt;.devcontainer/Dockerfile&lt;/code&gt; that we did not have previously, our working directory will now look like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;working-directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ .devcontainer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|   |__ devcontainer.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|   |__ Dockerfile         # predefined dev container Dockerfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ index.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|__ Dockerfile             # our self-defined Dockerfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If we look at the &lt;code&gt;devcontainer.json&lt;/code&gt; file we will see something similar to what we had before:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Node.js 12&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;dockerFile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Dockerfile&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Set *default* container specific settings.json values on container create.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;settings&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;terminal.integrated.shell.linux&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/bin/bash&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Add the IDs of extensions you want installed when the container is created.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;extensions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;dbaeumer.vscode-eslint&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You may, however, note that the &lt;code&gt;dockerFile&lt;/code&gt; property is missing, this just means that VSCode will use the default &lt;code&gt;Dockerfile&lt;/code&gt; which has been created in the &lt;code&gt;.devcontainer&lt;/code&gt; directory&lt;/p&gt;
&lt;p&gt;We can go ahead and change the name if we want, we should also add the &lt;code&gt;forwardPorts&lt;/code&gt; option as we did previously:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;forwardPorts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now looking at the &lt;code&gt;Dockerfile&lt;/code&gt; which defines the base development container:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;dockerfile&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; mcr.microsoft.com/vscode/devcontainers/javascript-node:0-12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is a bit different to ours because Visual Studio Code will handle the file copying and port exposing on its own for the development container. Note that this configuration can only be used for development and can&amp;#39;t really be deployed as a production container. This type of setup is necessary if our development image and production image will be different (which they usually are)&lt;/p&gt;
&lt;p&gt;Now that the development container has been set-up, we can use &lt;code&gt;ctrl + shift + p&lt;/code&gt; and &lt;code&gt;Remote-Containers: Reopen in Container&lt;/code&gt; to open our development container, from here we can work on our application and run the application the same as we did before&lt;/p&gt;
&lt;h3&gt;Which Method to Use&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ve looked at two different methods for configuring our development container, either of which can be used in any project. Below are my recommendations:&lt;/p&gt;
&lt;p&gt;If you&amp;#39;ve got an existing &lt;code&gt;Dockerfile&lt;/code&gt; and your development container can be the same as your production container, for things like simple &lt;code&gt;node.js&lt;/code&gt; or &lt;code&gt;python&lt;/code&gt; apps, and you don&amp;#39;t want to maintain another &lt;code&gt;Dockerfile&lt;/code&gt; then this may be a quick solution to opt for&lt;/p&gt;
&lt;p&gt;Otherwise, if your development container needs to be different from your production one then it&amp;#39;s probably easier to start with a predefined VSCode Container as a base and add in any development configuration you need to the &lt;code&gt;.devcontainer/Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Lastly, if you don&amp;#39;t have an existing &lt;code&gt;Dockerfile&lt;/code&gt; at all then I&amp;#39;d suggest using a predefined one so that even if it&amp;#39;s not fully configured you&amp;#39;ve got a relatively good starting point, especially when working with more complex languages and frameworks as a custom &lt;code&gt;Dockerfile&lt;/code&gt; for these can be some work to configure&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;In this post, we&amp;#39;ve covered the basics of using Docker to run your applications in a container as well as how to define and build your images. We also looked at why we may want to use a container for development and how we can do this using Visual Studio Code&lt;/p&gt;
&lt;h3&gt;Further Reading&lt;/h3&gt;
&lt;p&gt;For some more in-depth information on Docker and VSCode Development Containers you can look at the following resources:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;/docs/containers-and-microservices/docker&quot; &gt;My General Docker Notes&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/docs/containers-and-microservices/docker&quot; &gt;Docker Basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/containers-and-microservices/build-an-express-app-with-mongo&quot; &gt;Express Application with MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/containers-and-microservices/docker-multi-stage&quot; &gt;Multi-stage Builds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/&quot; &gt;Docker&amp;#39;s Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/docs/remote/containers&quot; &gt;VSCode&amp;#39;s Remote Containers Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Node.js Dirname vs Resolve</title><link>https://nabeelvalley.co.za/blog/2020/25-09/dirname-vs-resolve.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/25-09/dirname-vs-resolve.html</guid><description>Working with paths using resolve and __dirname in Node.js</description><pubDate>Fri, 25 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Node.js Dirname vs Resolve&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Node.js has a few methods by which we can get the directory in which we are currently executing, and get paths relative to it&lt;/p&gt;
&lt;h2&gt;Get the Current Directory&lt;/h2&gt;
&lt;h3&gt;Process Directory&lt;/h3&gt;
&lt;p&gt;We can get the working directory from where we started the &lt;code&gt;node&lt;/code&gt; script with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; processDir&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;File/Module Directory&lt;/h3&gt;
&lt;p&gt;And we can get the directory in which the currently executing file is in with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fileDir&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; __dirname&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Get Path to a Target Location&lt;/h2&gt;
&lt;p&gt;To get an absolute path to a specific target file/directory we have a few methods&lt;/p&gt;
&lt;h3&gt;Joining Paths&lt;/h3&gt;
&lt;p&gt;We can use the &lt;code&gt;path&lt;/code&gt; module&amp;#39;s &lt;code&gt;join&lt;/code&gt; method to get a path given any path pieces you can go up or down a directory using the &lt;code&gt;../&lt;/code&gt; notation&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;path&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(basePath, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./downdir/myfile.txt&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(basePath, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;../updir&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Absolute Path from Process Directory&lt;/h3&gt;
&lt;p&gt;To get an absolute path from the process directory, you can use the &lt;code&gt;path&lt;/code&gt; module&amp;#39;s &lt;code&gt;resolve&lt;/code&gt; function:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;path&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; absPath&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./downdir/myfile.txt&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Like the &lt;code&gt;join&lt;/code&gt; method you can also use the &lt;code&gt;../&lt;/code&gt; notation to move up a directory&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using &lt;code&gt;resolve&lt;/code&gt; is basically shorthand for using &lt;code&gt;join&lt;/code&gt; with &lt;code&gt;process.cwd()&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; absPath&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(process.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;cwd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(), &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./downdir/myfile.txt&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Absolute Path from File/Module Directory&lt;/h3&gt;
&lt;p&gt;If it makes more sense to get the path relative to the executing file, you can use a combination of &lt;code&gt;__dirname&lt;/code&gt; and &lt;code&gt;join&lt;/code&gt; like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;path&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; absPath&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(__dirname, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./downdir/myfile.txt&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Backup SQL Server Database as Script</title><link>https://nabeelvalley.co.za/blog/2020/26-11/backup-database-as-script.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/26-11/backup-database-as-script.html</guid><description>Create a DB Backup/Restore Script using SQL Server</description><pubDate>Thu, 26 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Backup SQL Server Database as Script&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;To create a scripted backup of a database on SQL Server do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Right click on the database name &amp;gt; &lt;code&gt;Tasks&lt;/code&gt; &amp;gt; &lt;code&gt;Generate Scripts...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;Choose Objects&lt;/code&gt; screen select &lt;code&gt;Scriot entire database and all database objects&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;Set Scripting Options&lt;/code&gt; screen click on &lt;code&gt;Advanced&lt;/code&gt; and select:&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Script DROP and CREATE = Script CREATE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Types of data to script = Schema and data&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Set the location to save the script&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;Summary&lt;/code&gt; page you can click &lt;code&gt;Next&lt;/code&gt; which will start the generation&lt;/li&gt;
&lt;li&gt;Thereafter you can view the generated database script from the location it was generated to&lt;/li&gt;
&lt;/ol&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Highlight Specific Elements</title><link>https://nabeelvalley.co.za/blog/2020/29-09/highlight-specific-elements.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/29-09/highlight-specific-elements.html</guid><description>Add a border around all HTML Elements that match a CSS Selector to aid in debugging</description><pubDate>Tue, 29 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Highlight Specific Elements&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;You can highlight all HTML elements which respond to a specific CSS selector with the following. This can be useful for debugging purposes:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;document&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(selector)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;el&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (el.style.border &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;solid 2px red&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For example, the following &lt;code&gt;[id]&lt;/code&gt; selector will find all elements with an &lt;code&gt;id&lt;/code&gt; attribute:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;document&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;[id]&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;el&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (el.style.border &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;solid 2px red&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>URL Text Fragments</title><link>https://nabeelvalley.co.za/blog/2020/29-09/text-fragments.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2020/29-09/text-fragments.html</guid><description>Link to, and highlight, content on any part of a Web page with the Text Fragment directive</description><pubDate>Tue, 29 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;URL Text Fragments&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When linking to a webpage it can be useful to link to a specific part of a page. Using a hash in the URl you can link to the &lt;code&gt;id&lt;/code&gt; attribute in the HTML of a page&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;https://my.website.com#overview&lt;/code&gt; would link to the element with &lt;code&gt;id=&amp;quot;overview&amp;quot;&lt;/code&gt; in the HTML&lt;/p&gt;
&lt;p&gt;However, it may be useful for us to link to a general piece of text on a page, we can use &lt;em&gt;text fragments&lt;/em&gt; to do so. These work similar to the way a hash does, but we can link to any text on a page even if it does not have an &lt;code&gt;id&lt;/code&gt;. Additionally, the user&amp;#39;s browser will highlight the text set to draw the user&amp;#39;s attention to it&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that at the moment only Chromium based browsers support this&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To do this, we need to identifiy the text on the page we want to link to. Say we&amp;#39;d like to link to the first paragraph of this page, we can use the &lt;strong&gt;text directive&lt;/strong&gt; (&lt;code&gt;#:~:text=&lt;/code&gt;) param in the URL to link to specific text instead of just the &lt;code&gt;#&lt;/code&gt; like we use for an ID&lt;/p&gt;
&lt;p&gt;We would need to take the part of the text we want to focus, URL encode it, then add it to the &lt;strong&gt;text directive&lt;/strong&gt; the final URL may look something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;https://my.website.com/#:~:text=When%20linking%20to%20a%20webpage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If you need to highlight a larger piece of text, you can use the start and end of your text segment, separated by a comma, for example selecting the entire first paragraph of this post:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;https://my.website.com/#:~:text=when%20linking,HTML%20of%20a%20page&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The link below should link to the first paragraph of this page if opened in a new tab (provided your browser supports text fragments):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;#:~:text=when%20linking,HTML%20of%20a%20page&quot; &gt;ctrl + click me&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can read more about text fragments in URLs on &lt;a href=&quot;https://web.dev/text-fragments/&quot; &gt;web.dev&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Serialize a JsonValue Array using F# and FSharp.Data&#39;s JsonProvider</title><link>https://nabeelvalley.co.za/blog/2021/01-03/serialize-jsonvalue-array-fsharp.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/01-03/serialize-jsonvalue-array-fsharp.html</guid><description>Making use of the FSharp.Data JsonProvider and the serialization of JsonProvider arrays into JSON</description><pubDate>Mon, 01 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Serialize a JsonValue Array using F# and FSharp.Data&amp;#39;s JsonProvider&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When working with the &lt;code&gt;FSharp.Data.JsonProvider&lt;/code&gt; type provider you may encounter a need to serialize a &lt;code&gt;JsonValue array&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s take a look at an example where this may be necessary:&lt;/p&gt;
&lt;p&gt;First, we&amp;#39;ll define the type of our data using a type provider, in this case it&amp;#39;s connected to the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;data/api-response.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;data&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;caption&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;caption&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;media_type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;IMAGE&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;media_url&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;url_to_image&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;paging&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;cursors&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;before&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hash&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;after&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hash&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;next&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;full_request_url&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the F# file that&amp;#39;s using this as the basis for the type definition is as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FSharp.Data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ApiResponse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; JsonProvider&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./data/api-response.json&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; SampleIsList&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can also create some sample data using the &lt;code&gt;ApiResponse.Parse&lt;/code&gt; method that&amp;#39;s now defined on our type thanks to the JsonProvider&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// get some sample data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sampleData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ApiResponse.Parse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&amp;quot;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;data&amp;quot;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          &amp;quot;id&amp;quot;: &amp;quot;id&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          &amp;quot;caption&amp;quot;: &amp;quot;caption&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          &amp;quot;media_type&amp;quot;: &amp;quot;IMAGE&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          &amp;quot;media_url&amp;quot;: &amp;quot;url_to_image&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;paging&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;quot;cursors&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          &amp;quot;before&amp;quot;: &amp;quot;hash&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;          &amp;quot;after&amp;quot;: &amp;quot;hash&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;quot;next&amp;quot;: &amp;quot;full_request_url&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If you were to use the &lt;code&gt;sampleData&lt;/code&gt; object and try to parse it to JSON you could directly call the &lt;code&gt;sampleData.JsonValue.ToString()&lt;/code&gt; method. As designed, this immediately returns the JSON representation of the object&lt;/p&gt;
&lt;p&gt;However, when we take a look at the &lt;code&gt;sampleData.Data&lt;/code&gt; property, we will notice this is a &lt;code&gt;Datum array&lt;/code&gt;, the problem here is that the &lt;code&gt;array&lt;/code&gt; type doesn&amp;#39;t have &lt;code&gt;JsonValue&lt;/code&gt; property&lt;/p&gt;
&lt;p&gt;However, if we look at how &lt;code&gt;JsonValue&lt;/code&gt; is defined we will see the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;union JsonValue &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; String &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Number &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; decimal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Float &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; float&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Record &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; properties&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; JsonValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Array &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; elements&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; JsonValue&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Boolean &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; bool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Based on this, we can see that an &lt;code&gt;Array of elements&lt;/code&gt; can be seen as a &lt;code&gt;JsonValue array&lt;/code&gt;, using this information, we can make use of the &lt;code&gt;JsonValue.Array&lt;/code&gt; constructor and the &lt;code&gt;JsonValue&lt;/code&gt; property of each of the elements of the &lt;code&gt;Data&lt;/code&gt; property to convert the &lt;code&gt;JsonValue array&lt;/code&gt; to a &lt;code&gt;JsonValue&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; jsonValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // get the property we want&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    sampleData.Data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // extract the JsonValue property from each element&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Array.map &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(fun&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; p &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; p.JsonValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // pass into the JsonValue.Array constructor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; JsonValue.Array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jsonValue.ToString&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Logging Aliases for Javascript</title><link>https://nabeelvalley.co.za/blog/2021/02-11/javascript-quick-logger.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/02-11/javascript-quick-logger.html</guid><description>Console and file-based logging alias for Javascript</description><pubDate>Tue, 02 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Logging Aliases for Javascript&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I often find myself writing a function to &lt;code&gt;JSON.stringify&lt;/code&gt; some data to log in either a pretty or flat structure&lt;/p&gt;
&lt;p&gt;It&amp;#39;s just more of a convenience method, and it&amp;#39;s pretty much the same as doing &lt;code&gt;console.log(JSON.stringify(data))&lt;/code&gt; and looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;pretty&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;null&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, pretty &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then, when I need to log something:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;_&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Or, if I want to pretty print the JSON&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;_&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(myData, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Jenkins: A Git process may have crashed in the repository</title><link>https://nabeelvalley.co.za/blog/2021/03-02/jenkins-git-process-crashed.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/03-02/jenkins-git-process-crashed.html</guid><description>Repair an issue preventing Jenkins from running Git processes</description><pubDate>Wed, 03 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Jenkins: A Git process may have crashed in the repository&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Taken from &lt;a href=&quot;https://stackoverflow.com/questions/38004148/another-git-process-seems-to-be-running-in-this-repository&quot; &gt;this StackOverflow answer&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Another git process seems to be running in this repository, e.g.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;an edirot opened by &amp;#39;git commit&amp;#39;. Please make sure all processes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;are terminated then try again. If it still fails, a git process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;may have crashed in this repository earlier:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;remove the file manually to continue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Sometimes when using Jenkins a Git process may crash or timeout resulting in an error message like the above one. This can result in issues when running later Git steps or running other Git steps in the repository in the Jenkins workspace&lt;/p&gt;
&lt;p&gt;The simplest way I&amp;#39;ve found to fix this is to simply delete the &lt;code&gt;.git/index.lock&lt;/code&gt; or &lt;code&gt;.git/shallow.lock&lt;/code&gt; file from the workspace that&amp;#39;s giving the issue and run again&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Multi-module Python project using an __init__.py file</title><link>https://nabeelvalley.co.za/blog/2021/06-05/multi-module-python-projects.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/06-05/multi-module-python-projects.html</guid><description>How to work with modules and handle the &#39;ModuleNotFoundError: No module named ...&#39; error</description><pubDate>Thu, 06 May 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Multi-module Python project using an __init__.py file&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When creating a multi-module project for Python, especially when coming from another language ecosystem, you may encounter issues importing code from other files, let&amp;#39;s take a look at this&lt;/p&gt;
&lt;h2&gt;The Modules&lt;/h2&gt;
&lt;p&gt;In our project, we&amp;#39;ve got the following files:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;package1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  |- module1.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;package2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  |- namespace2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       |- module2.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;main.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Let&amp;#39;s say each of our modules export a function, here&amp;#39;s the code for them:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;package1/module1.py&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;py&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;def&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; hello_p1_m1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;hello&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;package2/subpackage1/module1.py&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;py&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;def&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; hello_p2_s1_m1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;hello&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;The Main&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve got our files with their functions separated, we try using them from the &lt;code&gt;main.py&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;py&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; package1.module1 &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; p1m1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; package2.namespace1.module1 &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; p2s1m1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;print&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(p1m1.hello_p1_m1())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;print&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(p2n1m1.hello_p2_s1_m1())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;The Error&lt;/h2&gt;
&lt;p&gt;Now, we try to run this using &lt;code&gt;python&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;python&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; main.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we get the following error:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  File &amp;quot;main.py&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    import package1.module1 as p1m1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;ImportError: No module named package1.module1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;Now, this can be pretty annoying, but the solution is very simple. Python identifies a &lt;code&gt;module&lt;/code&gt; as a single file, and the assumption that leads to the issue above is that we assume a &lt;code&gt;package&lt;/code&gt; has the same convention of just being a directory&lt;/p&gt;
&lt;p&gt;However, a &lt;code&gt;packgage&lt;/code&gt; requires an &lt;code&gt;__init__.py&lt;/code&gt; file to be defined so that they are recognized correctly&lt;/p&gt;
&lt;p&gt;So, we need to add two files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;package1/__init__.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package2/subpackage1/__init__.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, these files are completely empty, and only serve as information. Note that we don&amp;#39;t need to include a file in &lt;code&gt;package2&lt;/code&gt; directly as this directory does not contain any modules within it so is not really a package in itself and is simply a wrapper &lt;code&gt;subpackage1&lt;/code&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Setup HomeAssistant RaspberryPi with WiFi configured</title><link>https://nabeelvalley.co.za/blog/2021/09-03/configure-home-assistant-raspberrypi-wifi.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/09-03/configure-home-assistant-raspberrypi-wifi.html</guid><description>Enable a HomeAssistant flashed RaspberryPi to operate over WiFi using config files</description><pubDate>Tue, 09 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Setup HomeAssistant RaspberryPi with WiFi configured&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;A short lil guide to setting up Home Assistant on a RaspberryPi using WiFi instead of Ethernet&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download Balena Etcher and install from &lt;a href=&quot;https://www.balena.io/etcher/&quot; &gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Go to the HomeAssistant website and copy the relevant release URL from &lt;a href=&quot;https://github.com/home-assistant/operating-system/releases/download/5.12/hassos_rpi3-64-5.12.img.xz&quot; &gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Connect your RaspberryPi&amp;#39;s SD card to your computer&lt;/li&gt;
&lt;li&gt;Open Balena Etcher and select &lt;code&gt;Flash from URL&lt;/code&gt; and select the RaspberryPi&amp;#39;s SD to flash to&lt;/li&gt;
&lt;li&gt;Once flashing is complete, open the RaspberryPi&amp;#39;s SD in File Explorer, and create the following file:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;RASPBERRYPIDRIVE/CONFIG/network/my-network&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;!cat .\my-network&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;[connection]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;id=my-network&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;uuid=72111c67-4a5d-4d5c-925e-f8ee26efb3c3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;type=802-11-wireless&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;[802-11-wireless]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;ssid=YOUR_WIFI_NETWORK_NAME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;#hidden=true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;[802-11-wireless-security]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;auth-alg=open&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;key-mgmt=wpa-psk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;psk=YOUR_WIFI_PASSWORD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;[ipv4]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;method=auto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;[ipv6]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;addr-gen-mode=stable-privacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;method=auto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Be sure to use &lt;code&gt;LF&lt;/code&gt; line endings, additional information on this setup can be found &lt;a href=&quot;https://github.com/home-assistant/operating-system/blob/dev/Documentation/network.md&quot; &gt;on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>XUnit with F#</title><link>https://nabeelvalley.co.za/blog/2021/10-04/xunit-with-fsharp.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/10-04/xunit-with-fsharp.html</guid><description>Configuring and Testing F# applications using XUnit and the .NET Core CLI</description><pubDate>Sat, 10 Apr 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;XUnit with F#&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;An important part of writing any software is testing. Unit testing is an automated testing method in which we test individual components of our software to verify that their behaviour aligns with our expectations&lt;/p&gt;
&lt;p&gt;This post will take a look at the process of setting up a new F# library and two methods of configuring XUnit to test your project&amp;#39;s code&lt;/p&gt;
&lt;h2&gt;Create a Project&lt;/h2&gt;
&lt;p&gt;Before we can start testing we need a project that we can run tests on&lt;/p&gt;
&lt;p&gt;First, we&amp;#39;re going to create a folder that we can work in:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;mkdir&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; MyProject&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; MyProject&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can use the following command to create a new project in our &lt;code&gt;MyProject&lt;/code&gt; directory:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; classlib&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -lang=f&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;# -o MyProject.Lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The project that we created will contain the following &lt;code&gt;Library.ts&lt;/code&gt; file, this is the file that we&amp;#39;ll write tests for. First, we want to update the &lt;code&gt;hello&lt;/code&gt; function so that it returns a formatted string:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MyProject.Lib/Library.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyProject.Lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;module&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Say &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; hello name &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        sprintf &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%s&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Adding Tests&lt;/h2&gt;
&lt;p&gt;Depending on our preferred project structure we can either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add tests in a separate project&lt;/li&gt;
&lt;li&gt;Add test files alongside lib files&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Method 1: Create Tests in Separate Project&lt;/h3&gt;
&lt;p&gt;The standard method of .NET unit testing with XUnit is to make use of separate Project and Test solutions, so a normal test setup would look something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;MyProject.Lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;MyProject.Lib.Tests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;To add an new XUnit test project you can run:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; xunit&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -lang=f&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;# -o MyProject.Tests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then, so we&amp;#39;re able to test the code from &lt;code&gt;MyProject.Lib&lt;/code&gt;, we need to add a reference to it from the Test project we just created:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; MyProject.Tests&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; reference&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; MyProject.Lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then we can create a file in our test project called &lt;code&gt;LibraryTests.fs&lt;/code&gt; which will contain our test code which we will cover in the last section, as well as adding a reference to this file in the &lt;code&gt;MyProject.Tests.fsproj&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MyProject.Tests.fsproj&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;xml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Tests.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- Add the next line --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;LibraryTests.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Program.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Method 2: Create Tests Alongside Lib Files&lt;/h3&gt;
&lt;p&gt;The second method I&amp;#39;m going to discuss is keeping our &lt;code&gt;test.fs&lt;/code&gt; files alongside the code that the file is testing. The structure of our project is something more like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;MyProject.Lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; Library.fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; Library.test.fs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Overall I find this more manageable is the way I keep my test code in other languages and frameworks as well&lt;/p&gt;
&lt;p&gt;To implement this method we need to add some dependencies to our project&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;bash&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;cd&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; MyProject.Lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; package&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; Microsoft.NET.Test.Sdk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; package&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; xunit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dotnet&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; package&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; xunit.runner.visualstudio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then we can create a file in our project called &lt;code&gt;Library.test.fs&lt;/code&gt; which will contain our test code which we will cover next, as well as a reference to this file in the &lt;code&gt;MyProject.Lib.fsproj&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MyProject.Lib.fsproj&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;xml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Library.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- Add the next line --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Compile&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Include&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Library.test.fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;It&amp;#39;s important to note that this file must be added below the &lt;code&gt;Library.fs&lt;/code&gt; file as it will reference it for tests to run&lt;/p&gt;
&lt;h2&gt;Test Files&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;More detailed information on XUnit can be found in &lt;a href=&quot;/docs/dotnet/unit-testing-intro&quot; &gt;Unit Testing notes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since we&amp;#39;ve configured XUnit it may be useful to understand how these tests work in the context of F#. XUnit tests are organized into modules. Regardless of which of the two methods above you&amp;#39;re using the test files work the same&lt;/p&gt;
&lt;p&gt;Generally, a test file will contain:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A top-level module definition&lt;/li&gt;
&lt;li&gt;&lt;code&gt;open&lt;/code&gt; statements to import XUnit&lt;/li&gt;
&lt;li&gt;Test functions annotated with &lt;code&gt;Fact&lt;/code&gt; or &lt;code&gt;Theory&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;XUnit tests can be broken into 2 types:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Single-case tests without input parameters inputs are labelled &lt;code&gt;Fact&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Multi-case tests which make use of input parameters are labelled &lt;code&gt;Theory&lt;/code&gt; and use &lt;code&gt;InlineData&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Fact&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s add the following content into our test file into one that tests the &lt;code&gt;hello&lt;/code&gt; function from our &lt;code&gt;Lib&lt;/code&gt; code with the input &lt;code&gt;&amp;quot;Name&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;LibraryTests.fs/Library.test.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;module&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; LibraryTests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Xunit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyProject.Lib.Say&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;Fact&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ``Say.hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Hello name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;quot; `` &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;name&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hello name&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; hello name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    Assert.Equal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;F# allows us to name our functions using special characters provided they&amp;#39;re enclosed in backticks as seen above. Naming test functions this way allows them to be more discriptive than more traditional variable names&lt;/p&gt;
&lt;p&gt;Additionally, there&amp;#39;s the normal XUnit test setup which includes calling our test function with some input and asserting something about it using &lt;code&gt;Assert.Equal&lt;/code&gt; from &lt;code&gt;XUnit&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Theory&lt;/h3&gt;
&lt;p&gt;We can add a &lt;code&gt;Theory&lt;/code&gt; to test our function with multiple different inputs:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;LibraryTests.fs/Library.test.fs&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;Theory&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;InlineData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hello name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;InlineData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ``Say.hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; concantenated string`` &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; hello name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    Assert.Equal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above we add the &lt;code&gt;InlineData&lt;/code&gt; attribute which allows us to provide inputs to our test, as well as specifying a &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;expected&lt;/code&gt; argument for our function. The test framework will then call our test using the arguments as specified in &lt;code&gt;InlineData&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;When we&amp;#39;re done our test file should have the following content:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;fs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;module&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; LibraryTests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Xunit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyProject.Lib.Say&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;Fact&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ``Say.hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Hello name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;quot; `` &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;name&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hello name&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; hello name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    Assert.Equal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;Theory&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;InlineData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hello name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[&amp;lt;InlineData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ``Say.hello &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; concantenated string`` &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; hello name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    Assert.Equal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Running Tests&lt;/h2&gt;
&lt;p&gt;In order to run tests we can use the &lt;code&gt;dotnet-cli&lt;/code&gt;. Depending on the method used you can run your test from the project&amp;#39;s root directory using the following command:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Method 1&lt;/strong&gt; - &lt;code&gt;dotnet test MyProject.Tests&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Method 2&lt;/strong&gt; - &lt;code&gt;dotnet test MyProject.Lib&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alternatively, tests can also be run from your IDE or Visual Studio Code with the &lt;code&gt;Ionide&lt;/code&gt; and &lt;code&gt;.NET Core Test Explorer&lt;/code&gt; extensions installed&lt;/p&gt;
&lt;h2&gt;Additional Resources&lt;/h2&gt;
&lt;p&gt;If you&amp;#39;d like a deeper look into F# or XUnit here are some of my other posts which cover those:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2019/30-10/fsharp-webapi&quot; &gt;Introduction to F# Web APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dotnet/intro-to-fs&quot; &gt;Introduction to F#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dotnet/fs-entity-framework&quot; &gt;Entity Framework with F#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dotnet/unit-testing-intro&quot; &gt;Introduction to Unit Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/dotnet/test-private-members&quot; &gt;Testing Private Members&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Nabeel Valley&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Template Literal Types with Typescript</title><link>https://nabeelvalley.co.za/blog/2021/16-08/typescript-template-literal-types.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/16-08/typescript-template-literal-types.html</guid><description>Defining type combinations using Template Literal types</description><pubDate>Mon, 16 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Template Literal Types with Typescript&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Template literal types provide us a way to combine &lt;code&gt;string types&lt;/code&gt; or &lt;code&gt;enums&lt;/code&gt; in Typescript.&lt;/p&gt;
&lt;p&gt;In the below example, we can make use of a &lt;code&gt;string type&lt;/code&gt; called &lt;code&gt;Action&lt;/code&gt; and an &lt;code&gt;enum&lt;/code&gt; called &lt;code&gt;Resource&lt;/code&gt; to define a type which is a combination of an action combined with a resource&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Action&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;UPDATE&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;CREATE&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;DELETE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;enum&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Resource&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Person&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Person&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Product&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Product&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Sale&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Sale&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// the `Lowercase` type concerts all string type options to lowercase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ResourceAction&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Resource&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Action&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Such that the &lt;code&gt;ResourceAction&lt;/code&gt; type is now defined as:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ResourceAction&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Person.UPDATE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Person.CREATE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Person.DELETE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Product.UPDATE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Product.CREATE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Product.DELETE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Sale.UPDATE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Sale.CREATE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Sale.DELETE&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, if you&amp;#39;re like me - you probably want your types to be consistent in some way. For this purpose, we can use the &lt;code&gt;Lowercase&lt;/code&gt; type as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ResourceActionLowercase&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Lowercase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Resource&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Action&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which results in the following types:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ResourceActionLowercase&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;person.update&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;person.create&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;person.delete&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;product.update&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;product.create&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;product.delete&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;sale.update&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;sale.create&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;sale.delete&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Building Serverless Apps using the Serverless Stack Framework</title><link>https://nabeelvalley.co.za/blog/2021/17-06/sst-framework.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/17-06/sst-framework.html</guid><description>Build, debug, and deploy serverless applications on AWS using SST and VSCode</description><pubDate>Thu, 17 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Building Serverless Apps using the Serverless Stack Framework&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Prior to doing any of the below you will require your &lt;code&gt;~/.aws/credentials&lt;/code&gt; file to be configured with the credentials for your AWS account&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Serverless Stack Framework&lt;/h2&gt;
&lt;p&gt;SST Framework is a framework built on top of CDK for working with Lambdas and other CDK constructs&lt;/p&gt;
&lt;p&gt;It provides easy CDK setups and a streamlined debug and deploy process and even has integration with the VSCode debugger to debug stacks on AWS&lt;/p&gt;
&lt;h3&gt;Init Project&lt;/h3&gt;
&lt;p&gt;To init a new project use the following command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npx&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; create-serverless-stack@latest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-sst-app&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --language&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; typescript&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which will create a Serverless Stack applocation using TypeScript&lt;/p&gt;
&lt;h3&gt;Run the App&lt;/h3&gt;
&lt;p&gt;You can run the created project in using the config defined in the &lt;code&gt;sst.json&lt;/code&gt; file:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;my-sst-app&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;stage&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;dev&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;region&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;us-east-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;lint&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;typeCheck&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using the following commands command will build then deploy a dev stack and allow you to interact with it via AWS/browser/Postman/etc.&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Additionally, running using the above command will also start the application with hot reloading enabled so when you save files the corresponding AWS resources will be redeployed so you can continue testing&lt;/p&gt;
&lt;h3&gt;The Files&lt;/h3&gt;
&lt;p&gt;The application is structured like a relatively normal Lambda/CDK app with &lt;code&gt;lib&lt;/code&gt; which contains the following CDK code:&lt;/p&gt;
&lt;h4&gt;Stack&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;lib/index.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; MyStack &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./MyStack&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@serverless-stack/resources&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;(app&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.App)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // Set default runtime for all functions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  app.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setDefaultFunctionProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    runtime: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;nodejs12.x&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; MyStack&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(app, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-stack&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // Add more stacks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@serverless-stack/resources&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyStack &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Stack&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;(scope&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.App, id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;, props&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.StackProps) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    super&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(scope, id, props)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Create the HTTP API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; api&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Api&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Api&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      routes: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET /&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/lambda.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Show API endpoint in output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addOutputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ApiEndpoint: api.httpApi.apiEndpoint,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And &lt;code&gt;src&lt;/code&gt; which contains the lambda code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/lambda.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    statusCode: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;200&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    headers: { &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    body: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`Hello, World! Your request was received at ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;requestContext&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Add a new Endpoint&lt;/h3&gt;
&lt;p&gt;Using the defined constructs it&amp;#39;s really easy for us to add an additional endpoint:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/hello.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    data: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Hello, World! This is another lambda but with JSON&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    statusCode: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;200&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    headers: { &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    body: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then in the stack we just update the routes:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; api&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Api&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Api&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  routes: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;GET /&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/lambda.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;GET /hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/hello.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// new endpoint handler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So that the full stack looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@serverless-stack/resources&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyStack &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Stack&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;(scope&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.App, id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;, props&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.StackProps) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    super&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(scope, id, props)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Create the HTTP API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; api&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Api&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Api&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      routes: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET /&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/lambda.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET /hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/hello.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Show API endpoint in output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addOutputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ApiEndpoint: api.httpApi.apiEndpoint,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;VSCode Debugging&lt;/h3&gt;
&lt;p&gt;SST supports VSCode Debugging, all that&amp;#39;s required is for you to create a &lt;code&gt;.vscode/launch.json&lt;/code&gt; filw with the following content:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.vscode/launch.json&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;version&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.2.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;configurations&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Debug SST Start&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;request&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;launch&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;runtimeExecutable&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;npm&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;runtimeArgs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;start&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;port&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;9229&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;skipFiles&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;lt;node_internals&amp;gt;/**&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Debug SST Tests&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;node&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;request&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;launch&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;runtimeExecutable&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;${workspaceRoot}/node_modules/.bin/sst&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;args&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--runInBand&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--no-cache&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--watchAll=false&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;cwd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;${workspaceRoot}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;protocol&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;inspector&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;console&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;integratedTerminal&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;internalConsoleOptions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;neverOpen&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;env&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: { &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;&amp;quot;CI&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;disableOptimisticBPs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will then allow you to run &lt;code&gt;Debug SST Start&lt;/code&gt; which will configure the AWS resources using the &lt;code&gt;npm start&lt;/code&gt; command and connect the debugger to the instance so you can debug your functions locally as well as make use of the automated function deployment&lt;/p&gt;
&lt;h3&gt;Add a DB&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;From &lt;a href=&quot;https://serverless-stack.com/examples/how-to-create-a-crud-api-with-serverless-using-dynamodb.html&quot; &gt;these docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can define our table using the &lt;code&gt;sst.Table&lt;/code&gt; class:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; table&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  fields: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: sst.TableFieldType.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;STRING&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId: sst.TableFieldType.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;NUMBER&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  primaryIndex: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    partitionKey: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    sortKey: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;noteId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can add some endpoint definitions for the functions we&amp;#39;ll create as well as access to the table name via the environment:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; api&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Api&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Api&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  defaultFunctionProps: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    timeout: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;60&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// increase timeout so we can debug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    environment: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      tableName: table.dynamodbTable.tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  routes: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // .. other routes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;GET  /notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/getAll.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// userId in query&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;GET  /notes/{noteId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/get.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// userId in query&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;POST /notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/create.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And lastly we can grant the permissions to our &lt;code&gt;api&lt;/code&gt; to access the &lt;code&gt;table&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;api.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;attachPermissions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([table])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Adding the above to the &lt;code&gt;MyStack.ts&lt;/code&gt; file results in the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@serverless-stack/resources&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyStack &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Stack&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;(scope&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.App, id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;, props&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.StackProps) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    super&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(scope, id, props)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; table&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      fields: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        userId: sst.TableFieldType.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;STRING&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        noteId: sst.TableFieldType.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;STRING&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      primaryIndex: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        partitionKey: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        sortKey: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;noteId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Create the HTTP API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; api&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Api&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Api&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      defaultFunctionProps: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        timeout: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;60&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// increase timeout so we can debug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        environment: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          tableName: table.dynamodbTable.tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      routes: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        // .. other routes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET  /notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/getAll.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// userId in query&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET  /notes/{noteId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/get.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// userId in query&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;POST /notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/create.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    api.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;attachPermissions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([table])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Show API endpoint in output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addOutputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ApiEndpoint: api.httpApi.apiEndpoint,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Before we go any further, we need to install some dependencies in our app, particularly &lt;code&gt;uuid&lt;/code&gt; for generating unique id&amp;#39;s for notes, we can install a dependency with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; install&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; uuid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; install&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; aws-sdk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Define Common Structures&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ll also create some general helper functions for returning responses of different types, you can view the details for their files below but these just wrap the response in a status and header as well as stringify the body&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/responses/successResponse.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    statusCode: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;200&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    headers: { &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    body: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; successResponse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;src/responses/badResuestsResponse.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;msg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    statusCode: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;400&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    headers: { &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    body: msg,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; badRequestResponse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;src/responses/internalErrorResponse.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;msg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(msg)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    statusCode: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;500&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    headers: { &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    body: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;internal error&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we&amp;#39;ve also got a &lt;code&gt;Note&lt;/code&gt; type which will be the data that gets stored/retreived:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/notes/Note.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  noteId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  createdAt&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Note&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Access DB&lt;/h3&gt;
&lt;p&gt;Once we&amp;#39;ve got a DB table defined as above, we can then access the table to execute different queries&lt;/p&gt;
&lt;p&gt;We would create a DB object instance using:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Create&lt;/h4&gt;
&lt;p&gt;A &lt;code&gt;create&lt;/code&gt; is the simplest one of the database functions for us to implement, this uses the &lt;code&gt;db.put&lt;/code&gt; function with the &lt;code&gt;Item&lt;/code&gt; to save which is of type &lt;code&gt;Note&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;put&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ TableName: tableName, Item: item }).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Get&lt;/h4&gt;
&lt;p&gt;We can implement a &lt;code&gt;getOne&lt;/code&gt; function by using &lt;code&gt;db.get&lt;/code&gt; and providing the full &lt;code&gt;Key&lt;/code&gt; consisting of the &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;noteId&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getOne&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;noteId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      TableName: tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Key: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        userId: userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        noteId: noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result.Item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;GetAll&lt;/h4&gt;
&lt;p&gt;We can implement a &lt;code&gt;getByUserId&lt;/code&gt; function which will make use of &lt;code&gt;db.query&lt;/code&gt; and use the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt; to populate the &lt;code&gt;KeyConditionExpression&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getByUserId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;query&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      TableName: tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      KeyConditionExpression: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId = :userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ExpressionAttributeValues: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;:userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result.Items&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Define Lambdas&lt;/h3&gt;
&lt;p&gt;Now that we know how to write data to Dynamo, we can implement the following files for the endpoints we defined above:&lt;/p&gt;
&lt;h4&gt;Create&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDB } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { v1 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;uuid&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; internalErrorResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/internalErrorResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; successResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/successResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; badRequestResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/badRequestResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Note &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./Note&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; toItem&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: data,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;v1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content: content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    createdAt: Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event.body &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;{}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: data.userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content: data.content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isValid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.content &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;put&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ TableName: tableName, Item: item }).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;tableName is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId and content are required&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; toItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data.userId, data.content)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tableName, item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Get&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;src/notes/get.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDB } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; badRequestResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/badRequestResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; internalErrorResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/internalErrorResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; successResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/successResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; RequestParams&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  noteId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; RequestParams&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pathData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.pathParameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queryData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.queryStringParameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId: pathData?.noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: queryData?.userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isValid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; RequestParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.noteId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getOne&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;noteId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      TableName: tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Key: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        userId: userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        noteId: noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result.Item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;tableName is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;#39;noteId is required in path, userId is required in query&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getOne&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    data.noteId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(items)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDB } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; badRequestResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/badRequestResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; internalErrorResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/internalErrorResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; successResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/successResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; RequestParams&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  noteId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; RequestParams&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pathData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.pathParameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queryData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.queryStringParameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId: pathData?.noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: queryData?.userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isValid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; RequestParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.noteId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getOne&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;noteId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      TableName: tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      Key: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        userId: userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        noteId: noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result.Item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;tableName is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;#39;noteId is required in path, userId is required in query&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getOne&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    data.noteId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(items)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;GetAll&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;src/notes/getAll.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDB } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; badRequestResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/badRequestResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; internalErrorResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/internalErrorResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; successResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/successResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathParams&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathParams&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.queryStringParameters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: data?.userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isValid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getByUserId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;query&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      TableName: tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      KeyConditionExpression: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId = :userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ExpressionAttributeValues: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;:userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result.Items&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;tableName is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId is required in query&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getByUserId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tableName, data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(items)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Testing&lt;/h4&gt;
&lt;p&gt;Once we&amp;#39;ve got all the above completed, we can actually test our endpoints and create and read back data&lt;/p&gt;
&lt;p&gt;&lt;code&gt;create&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;http&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;POST&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; https://AWS_ENDPOINT_HERE/notes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;userId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;USER_ID&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which responds with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;http&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;200&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;createdAt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1619177078298&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;noteId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;NOTE_ID_UUID&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;userId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;USER_ID&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;get&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;http&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;GET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; https://AWS_ENDPOINT_HERE/notes/NOTE_ID_UUID?userId=USER_ID&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;http&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;200&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;createdAt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1619177078298&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;noteId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;NOTE_ID_UUID&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;userId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;USER_ID&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;getAll&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;http&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;GET&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; htttps://AWS_ENDPOINT_HERE/notes?userId=USER_ID&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;http&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;200&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;createdAt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1619177078298&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;noteId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;NOTE_ID_UUID&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;userId&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;USER_ID&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Creating Notes Using a Queue&lt;/h3&gt;
&lt;p&gt;When working with microservices a common pattern is to use a message queue for any operations that can happen in an asynchronous fashion, we can create an SQS queue which we can use to stage messages and then separately save them at a rate that we&amp;#39;re able to process them&lt;/p&gt;
&lt;p&gt;In order to make this kind of logic we&amp;#39;re going to break up our &lt;code&gt;create&lt;/code&gt; data flow - a the moment it&amp;#39;s this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;lambda -&amp;gt; dynamo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;return &amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We&amp;#39;re going to turn it into this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;lambda1 -&amp;gt; sqs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt; return &amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;          sqs -&amp;gt; lambda2 -&amp;gt; dynamo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This kind of pattern becomes especially useful if we&amp;#39;re doing a lot more stuff with the data other than just the single DB operation and also allows us to retry things like saving to the DB if we have errors, etc.&lt;/p&gt;
&lt;p&gt;A more complex data flow could look something like this (not what we&amp;#39;re implementing):&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;lambda1 -&amp;gt; sqs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt; return &amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           sqs -&amp;gt; lambda2 -&amp;gt; dynamo // save to db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;               -&amp;gt; lambda3 -&amp;gt; s3     // generate a report&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           sqs &amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           sqs -&amp;gt; lambda4           // send an email&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Create Queue&lt;/h4&gt;
&lt;p&gt;SST provides us with the &lt;code&gt;sst.Queue&lt;/code&gt; class that we can use for this purpose&lt;/p&gt;
&lt;p&gt;To create a Queue you can use the following in stack:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Queue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;NotesQueue&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  consumer: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/consumers/createNote.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;queue.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;attachPermissions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([table])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;queue.consumerFunction?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEnvironment&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;#39;tableName&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  table.dynamodbTable.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above code does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;queue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Give the queue permission to access the &lt;code&gt;table&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;tableName&lt;/code&gt; environment variable to the &lt;code&gt;queue&lt;/code&gt;&amp;#39;s &lt;code&gt;consumerFunction&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will also need to grant permissions to the API to access the &lt;code&gt;queue&lt;/code&gt; so that our &lt;code&gt;create&lt;/code&gt; handler is able to add messages to the &lt;code&gt;queue&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;api.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;attachPermissions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([table, queue])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which means our Stack now looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lib/MyStack.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@serverless-stack/resources&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyStack &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Stack&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;(scope&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.App, id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;, props&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; sst.StackProps) &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    super&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(scope, id, props)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; table&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      fields: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        userId: sst.TableFieldType.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;STRING&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        noteId: sst.TableFieldType.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;STRING&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      primaryIndex: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        partitionKey: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        sortKey: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;noteId&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Queue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;NotesQueue&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      consumer: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/consumers/createNote.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    queue.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;attachPermissions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([table])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    queue.consumerFunction?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEnvironment&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;#39;tableName&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      table.dynamodbTable.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Create the HTTP API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; api&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; sst.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Api&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Api&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      defaultFunctionProps: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        timeout: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;60&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// increase timeout so we can debug&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        environment: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          tableName: table.dynamodbTable.tableName,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          queueUrl: queue.sqsQueue.queueUrl,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      routes: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET  /&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/lambda.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET  /hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/hello.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET  /notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/getAll.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;POST /notes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/create.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;#39;GET  /notes/{noteId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;src/notes/get.handler&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    api.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;attachPermissions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([table, queue])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Show API endpoint in output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addOutputs&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ApiEndpoint: api.httpApi.apiEndpoint,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Update the Create Handler&lt;/h4&gt;
&lt;p&gt;Since we plan to create notes via a queue we will update our &lt;code&gt;create&lt;/code&gt; function in the handler to create a new message in the &lt;code&gt;queue&lt;/code&gt;, this is done using the &lt;code&gt;SQS&lt;/code&gt; class from &lt;code&gt;aws-sdk&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { SQS } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; SQS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once we&amp;#39;ve got our instance, the &lt;code&gt;create&lt;/code&gt; function is done by means of the &lt;code&gt;queue.sendMessage&lt;/code&gt; function:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;queueUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; queue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sendMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      QueueUrl: queueUrl,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      DelaySeconds: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      MessageBody: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Lastly, our &lt;code&gt;handler&lt;/code&gt; remains mostly the same with the exception of some additional validation to check that we have the &lt;code&gt;queue&lt;/code&gt; connection information in the environment:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // pre-save validation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.queueUrl &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;queueUrl is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queueUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.queueUrl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId and content are required&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // save process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; toItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data.userId, data.content)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; creatresult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(queueUrl, item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;creatresult.MessageId) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;MessageId is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Implementing the above into the &lt;code&gt;create&lt;/code&gt; handler means that our &lt;code&gt;create.ts&lt;/code&gt; file now looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/notes/create.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { v1 } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;uuid&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; internalErrorResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/internalErrorResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; successResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/successResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; badRequestResponse &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../responses/badRequestResponse&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Note &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./Note&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { SQS } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; SQS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// helper functions start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; toItem&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: data,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;v1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content: content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    createdAt: Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event.body &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;{}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: data.userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content: data.content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isValid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.userId &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.content &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// helper functions end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;queueUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; queue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;sendMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      QueueUrl: queueUrl,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      DelaySeconds: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      MessageBody: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyHandlerV2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  event&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; APIGatewayProxyEventV2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // pre-save validation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.queueUrl &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;queueUrl is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; queueUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.queueUrl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; badRequestResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;userId and content are required&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // save process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; toItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data.userId, data.content)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; creatresult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(queueUrl, item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;creatresult.MessageId) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;internalErrorResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;MessageId is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; successResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Add Queue-Based Create Handler&lt;/h4&gt;
&lt;p&gt;Now that we&amp;#39;ve updated our logic to save the notes into the &lt;code&gt;queue&lt;/code&gt;, we need to add the logic for the &lt;code&gt;src/consumers/createNote.handler&lt;/code&gt; consumer function as we specified above, this handler will be sent an &lt;code&gt;SQSEvent&lt;/code&gt; and will make use of the DynamoDB Table we gave it permissions to use&lt;/p&gt;
&lt;p&gt;First, we take the &lt;code&gt;create&lt;/code&gt; function that was previously on the &lt;code&gt;create.ts&lt;/code&gt; file for saving to the DB:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/consumers/createNote.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDB } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; createResult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;put&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ TableName: tableName, Item: item })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;createResult) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;create failed&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; createResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We&amp;#39;ll also need a function for parsing the &lt;code&gt;SQSRecord&lt;/code&gt; object into a &lt;code&gt;Note&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/consumers/createNote.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;record&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SQSRecord&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;noteId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createdAt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(record.body) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do this to ensure we only extract information we need&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    createdAt,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And finally we consume the above through the &lt;code&gt;handler&lt;/code&gt;, you can see in the below code that we are iterating over the &lt;code&gt;event.Records&lt;/code&gt; object, this is because the &lt;code&gt;SQSEvent&lt;/code&gt; adds each new event into this array, the reason for this is because we can also specify batching into our Queue so that the handler is only triggered after &lt;code&gt;n&lt;/code&gt; events instead of each time, and though this isn&amp;#39;t happening in our case, we still should handle this for our handler:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;src/consumers/createNote.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SQSHandler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // pre-save environment check&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;tableName is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.Records.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; r&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.Records[i]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(r)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tableName, item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Putting all the above together our &lt;code&gt;createNote.ts&lt;/code&gt; file now has the following code:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { SQSHandler, SQSRecord } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-lambda&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Note &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../notes/Note&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDB } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;aws-sdk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; DynamoDB.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;DocumentClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; createResult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;put&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ TableName: tableName, Item: item })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;createResult) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;create failed&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; createResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;record&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SQSRecord&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;noteId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;createdAt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(record.body) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Note&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do this to ensure we only extract information we need&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    noteId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    createdAt,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SQSHandler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;tableName is undefined&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tableName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; process.env.tableName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.Records.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; r&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; event.Records[i]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseBody&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(r)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tableName, item)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This completes the implementation of the asynchronous saving mechanism for notes. As far as a consumer of our API is concerned, nothing has changed and they will still be able to use the API exactly as we had in the &lt;a href=&quot;#testing&quot; &gt;Testing section above&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Deploy&lt;/h2&gt;
&lt;p&gt;Thus far, we&amp;#39;ve just been running our API in &lt;code&gt;debug&lt;/code&gt; mode via the &lt;code&gt;npm run start&lt;/code&gt; command, while useful for testing this adds a lot of code to make debugging possible, and isn&amp;#39;t something we&amp;#39;d want in our final deployed code&lt;/p&gt;
&lt;p&gt;Deploying using &lt;code&gt;sst&lt;/code&gt; is still very easy, all we need to do is run the &lt;code&gt;npm run deploy&lt;/code&gt; command and this will update our lambda to use a production build of the code instead:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;npm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Teardown&lt;/h2&gt;
&lt;p&gt;Lastly, the &lt;code&gt;sst&lt;/code&gt; CLI also provides us with a function to teardown our &lt;code&gt;start&lt;/code&gt;/&lt;code&gt;deploy&lt;/code&gt; code. So once you&amp;#39;re done playing around you can use this to teardown all your deployed services:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;npm run remove&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that running the &lt;code&gt;remove&lt;/code&gt; command will not delete the DB tables, you will need to do this manually&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Render Element by Tag Name in React</title><link>https://nabeelvalley.co.za/blog/2021/19-03/render-component-by-tag-name-react.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/19-03/render-component-by-tag-name-react.html</guid><description>Dynamically render a React Element given the name of the corresponding HTML element</description><pubDate>Fri, 19 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Render Element by Tag Name in React&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When using React it can sometimes be useful to render a standard HTML element given the element name dynamically as a prop&lt;/p&gt;
&lt;p&gt;React allows us to do this provided we store the element name in a variable that starts with a capital letter, as JSX requires this to render a custom element&lt;/p&gt;
&lt;p&gt;We can do something like this by defining a generic element in React which just takes in the name of the tag in addition to it&amp;#39;s usual props and children, something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;jsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; GenericElement&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tagName&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Tag&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;innerProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Tag&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; {...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;innerProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Tag&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then render this element by calling the &lt;code&gt;GenericElement&lt;/code&gt; with the &lt;code&gt;tagName&lt;/code&gt; prop and then any children we&amp;#39;d like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;jsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;GenericElement&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tagName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;h1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;I am an h1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;GenericElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Here&amp;#39;s a short example using &lt;a href=&quot;https://replit.com/@nabeelvalley/render-by-element-name#src/App.jsx&quot; &gt;Replit&lt;/a&gt; for reference, all the important stuff is in the &lt;code&gt;src/App.jsx&lt;/code&gt; file:&lt;/p&gt;
&lt;iframe height=&quot;700px&quot; width=&quot;100%&quot; src=&quot;https://replit.com/@nabeelvalley/render-by-element-name?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Custom Styles in Markdown</title><link>https://nabeelvalley.co.za/blog/2021/23-03/custom-styles-in-markdown.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/23-03/custom-styles-in-markdown.html</guid><description>Add styles for specific HTML elements in a markdown document</description><pubDate>Tue, 23 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Custom Styles in Markdown&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When working with markdown it can often be useful to be able to style elements using custom CSS&lt;/p&gt;
&lt;p&gt;We can accomplish this by including a &lt;code&gt;style&lt;/code&gt; tag. An example to illustrate this is changing the way a table renders in a specific document by changing the style of table rows to be striped, you would include the following CSS:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;tr&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;:nth-child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;even&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;#b2b2b2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;#f4f4f4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If the platform you&amp;#39;re displaying the HTML in already has the styles included then you may need to add &lt;code&gt;!important&lt;/code&gt; to override in the CSS:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;tr&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;:nth-child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;even&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;#b2b2b2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!important&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;#f4f4f4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!important&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;my-sample-doc.md&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;md&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-light-font-weight:bold;--shiki-dark:#91CBFF;--shiki-dark-font-weight:bold&quot; &gt;## Custom CSS in Markdown Example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;This is a document where tables are rendered with every second table row with a specific background and foreground colour&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;tr:nth-child(even) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  background-color: #b2b2b2!important;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  color: #f4f4f4!important;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/style&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;The above CSS will lead to the following table being rendered with alternating row colours:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;| Col 1 | Col 2 | Col 3 |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;| ----- | ----- | ----- |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;| A     | B     | C     |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;| 1     | 2     | 3     |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;| A1    | B2    | C3    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that depending on your markdown renderer the embeded style tags may be removed, you&amp;#39;ll have to look at your specific renderer/converter/platform to see whether this works for you&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With the converter I&amp;#39;m using, &lt;code&gt;showdown.js&lt;/code&gt;, this is how the table above looks (with &lt;code&gt;!important&lt;/code&gt; included to override my current table styles):&lt;/p&gt;
&lt;style&gt;
tr:nth-child(even) {
  background-color: #b2b2b2!important;
  color: #f4f4f4!important;
}
&lt;/style&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Col 1&lt;/th&gt;
&lt;th&gt;Col 2&lt;/th&gt;
&lt;th&gt;Col 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A1&lt;/td&gt;
&lt;td&gt;B2&lt;/td&gt;
&lt;td&gt;C3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Control a Raspberry Pi GPIO with Python</title><link>https://nabeelvalley.co.za/blog/2021/27-03/flicker-led-with-raspberry-pi.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/27-03/flicker-led-with-raspberry-pi.html</guid><description>Flicker and control and LED via a Raspberry Pi&#39;s GPIO Output pins using Python and RPi.GPIO</description><pubDate>Sat, 27 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Control a Raspberry Pi GPIO with Python&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Circuit Diagram&lt;/h2&gt;
&lt;p&gt;This script will make use of the GPIO Pins to flicker an LED&lt;/p&gt;
&lt;p&gt;The circuit diagram is below:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;2.069672131147541&quot; orientation=&quot;horizontal&quot; alt=&quot;led-circuit&quot; src=&quot;/optimized-images/public/content/blog/2021/27-03/led-circuit.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve used a &lt;span class=&quot;katex&quot; &gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; &gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;330&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot; &gt;Ω&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot; &gt;330\Omega&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; resistor for the resistor connected in series &lt;span class=&quot;katex&quot; &gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; &gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot; &gt;R_LED&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;, however the resistance for a given LED can be calculated with this equation (From &lt;a href=&quot;https://www.circuitspecialists.com/blog/how-to-determine-resistor-value-for-led-lighting/&quot; &gt;Circuit Specialists&lt;/a&gt;):&lt;/p&gt;
&lt;span class=&quot;katex&quot; &gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot; &gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;msub&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mrow&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;/mrow&gt;&lt;/msub&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot; &gt;R_{LED} = \frac{V_{source} - V_{LED}}{I_{LED}}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;
&lt;blockquote&gt;
&lt;p&gt;It&amp;#39;s important to connect the LED in the correct direction on the circuit&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;Below is a simple python script which will handle turning the GPIO pins on and off using the &lt;a href=&quot;https://pypi.org/project/RPi.GPIO/&quot; &gt;RPi.GPIO&lt;/a&gt; library&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;py&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; RPi.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; GPIO&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;pin &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 21&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;dur &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.setmode(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;BCM&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.setwarnings(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;False&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.setup(pin, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;OUT&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;while&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; True&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.output(pin, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;HIGH&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  print&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;LED ON&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  time.sleep(dur)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.output(pin, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;GPIO&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;LOW&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  print&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;LED OFF&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  time.sleep(dur)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Javascript Range Function</title><link>https://nabeelvalley.co.za/blog/2021/29-10/javascript-range.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2021/29-10/javascript-range.html</guid><description>Create ranges in Javascript</description><pubDate>Fri, 29 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Javascript Range Function&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Something i often find myself needing is a way to create a range in javascript, similar to what python has&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a basic implementation of something that works like that:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;start&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;includeEnd&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; space&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (end &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; includeEnd)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(count).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;fill&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;_&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;i&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; space)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above will output something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; withoutEnd&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;21&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// withoutEnd === [ 20, 20.2, 20.4, 20.6, 20.8 ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; withEnd&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;21&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// withEnd === [ 20, 20.25, 20.5, 20.75, 21 ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>React Top Level API</title><link>https://nabeelvalley.co.za/blog/2022/01-03/react-top-level-api.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/01-03/react-top-level-api.html</guid><description>Building complex react components using the React top-level API and TypeScript</description><pubDate>Tue, 01 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;React Top Level API&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;For a reference on the React Top-Level API you can take a look at &lt;a href=&quot;https://reactjs.org/docs/react-api.html&quot; &gt;the React Docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;React allows us to do lots of different things using concepts like composition and higher order components. Most of the time these methods are good enough for us to do what we want, however there are some cases where these methods can prove to be insufficient such as when building complex library components or components that need to allow for dynamic composition or do runtime modification of things like child component props, etc.&lt;/p&gt;
&lt;p&gt;For the above purposes we can make use of the React Top-Level API. For the purpose of this writeup I&amp;#39;ll be making use of the parts of this API that allow us to modify a component&amp;#39;s children and modify their props as well as how they&amp;#39;re rendered&lt;/p&gt;
&lt;h2&gt;Our Goal&lt;/h2&gt;
&lt;p&gt;For the purpose of this doc I&amp;#39;ll be using the React API to get to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Show the count of children (&lt;code&gt;Items&lt;/code&gt;) passed to a component (&lt;code&gt;Wrapper&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Render each child in a sub-wrapper &lt;code&gt;ItemWrapper&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Modify the props of the children by adding a &lt;code&gt;position&lt;/code&gt; prop&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When this is done, we want to render a component that results in the following markup:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;But a consumer can be used like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Using &lt;code&gt;React.Children&lt;/code&gt; to work with a component&amp;#39;s &lt;code&gt;children&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;React.Children&lt;/code&gt; API (see &lt;a href=&quot;https://reactjs.org/docs/react-api.html#reactchildren&quot; &gt;docs&lt;/a&gt;) provides us with some utilities for traversing the children passed to a component&lt;/p&gt;
&lt;p&gt;Before we can do any of the following, we need to define the structure of an item. Our &lt;code&gt;Item&lt;/code&gt; component is defined as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ItemProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ItemProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Use &lt;code&gt;React.Children.count&lt;/code&gt; to get the count&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;React.Children.count&lt;/code&gt; function counts the number of child nodes passed to a React component,
we can use it like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For our example, let&amp;#39;s start off by creating a &lt;code&gt;Count&lt;/code&gt; component that simply takes a &lt;code&gt;count&lt;/code&gt; prop and displays some text:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CountProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;CountProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Total: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can define our &lt;code&gt;Wrapper&lt;/code&gt; which will take &lt;code&gt;children&lt;/code&gt; and pass the &lt;code&gt;count&lt;/code&gt; to our &lt;code&gt;Count&lt;/code&gt; component:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Wrapper&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Count&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Use &lt;code&gt;React.Children.map&lt;/code&gt; to wrap each child&lt;/h3&gt;
&lt;p&gt;Next, the &lt;code&gt;React.Children.map&lt;/code&gt; function allows us to map over the children of an element and do stuff with it, for example:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Based on the above, we can define an &lt;code&gt;ItemWrapper&lt;/code&gt; as so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      backgroundColor: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lightgrey&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      padding: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;10px&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      margin: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;20px&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can update the &lt;code&gt;Wrapper&lt;/code&gt; to make use of &lt;code&gt;React.children.map&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Wrapper&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Count&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Use &lt;code&gt;React.cloneElement&lt;/code&gt; to change child props&lt;/h2&gt;
&lt;p&gt;Lastly, we want to append a &lt;code&gt;position&lt;/code&gt; prop to the &lt;code&gt;Item&lt;/code&gt;. To do this we can make use of the &lt;code&gt;React.cloneElement&lt;/code&gt; function which allows us to clone an element and modify the props of it. Using this function looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; childProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; child.props&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;child.props, position: index }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;cloneElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child, newProps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Integrating this into the &lt;code&gt;React.Children.map&lt;/code&gt; function above will result in our &lt;code&gt;Wrapper&lt;/code&gt; looking like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Wrapper&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;index&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; childProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; child.props&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;child.props, position: index }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;cloneElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child, newProps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Count&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Use &lt;code&gt;React.isValidElement&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We&amp;#39;ve completed most of what&amp;#39;s needed, however if for some reason our &lt;code&gt;child&lt;/code&gt; is not a valid react element our component may still crash. To get around this we can use the &lt;code&gt;React.isValidElement&lt;/code&gt; function&lt;/p&gt;
&lt;p&gt;We can update our &lt;code&gt;map&lt;/code&gt; function above to return &lt;code&gt;null&lt;/code&gt; if the element is not value:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;index&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValidElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; childProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; child.props&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;child.props, position: index }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;cloneElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child, newProps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which results in our &lt;code&gt;Wrapper&lt;/code&gt; now being:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Wrapper&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.Children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(children, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;index&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValidElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; childProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; child.props&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newProps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;child.props, position: index }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;cloneElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child, newProps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;newChild&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ItemWrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Count&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;items&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;The Result&lt;/h2&gt;
&lt;p&gt;Lastly, we&amp;#39;ll render the above using the &lt;code&gt;App&lt;/code&gt; component, the API for the above components should be composable as we outlined initially. The &lt;code&gt;App&lt;/code&gt; component will now look like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; App&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Apple&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Banana&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Chocolate&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;Wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the rendered HTML:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Total: 3&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;background-color: lightgrey; padding: 10px; margin: 20px;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Apple, 0&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;background-color: lightgrey; padding: 10px; margin: 20px;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Banana, 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;background-color: lightgrey; padding: 10px; margin: 20px;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Chocolate, 2&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div&gt;
  &lt;p&gt;Total: 3&lt;/p&gt;
  &lt;ul&gt;
    &lt;li style=&quot;background-color: lightgrey; padding: 10px; margin: 20px;&quot; &gt;
      &lt;div&gt;Apple, 0&lt;/div&gt;
    &lt;/li&gt;
    &lt;li style=&quot;background-color: lightgrey; padding: 10px; margin: 20px;&quot; &gt;
      &lt;div&gt;Banana, 1&lt;/div&gt;
    &lt;/li&gt;
    &lt;li style=&quot;background-color: lightgrey; padding: 10px; margin: 20px;&quot; &gt;
      &lt;div&gt;Chocolate, 2&lt;/div&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;&lt;p&gt;And lastly, if you&amp;#39;d like to interact with the code from this sample you can see it in &lt;a href=&quot;https://replit.com/@nabeelvalley/ReactTopLevelAPIExample#src/App.tsx&quot; &gt;this Repl&lt;/a&gt;&lt;/p&gt;
&lt;iframe height=&quot;700px&quot; width=&quot;100%&quot; src=&quot;https://replit.com/@nabeelvalley/ReactTopLevelAPIExample?lite=true#src/App.tsx&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Dev Tools Update</title><link>https://nabeelvalley.co.za/blog/2022/03-08/dev-tools-update.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/03-08/dev-tools-update.html</guid><description>Software development tools and languages I&#39;m using at the moment</description><pubDate>Wed, 03 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Dev Tools Update&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Programming Languages&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve primarily switched over to Typescript as my language for building applications, but I&amp;#39;ve also been learning Rust for the purpose of building some low-level libraries&lt;/p&gt;
&lt;p&gt;For Typescript, something I&amp;#39;ve been finding to be really informative is the &lt;a href=&quot;https://github.com/type-challenges/type-challenges&quot; &gt;Type Challenges Repository&lt;/a&gt; which has a lot of challenges along with solutions for modeling and solving complex problems using Typescript&amp;#39;s type system&lt;/p&gt;
&lt;p&gt;For Rust, the &lt;a href=&quot;https://doc.rust-lang.org/book/&quot; &gt;Rust Book&lt;/a&gt; along with the &lt;a href=&quot;https://www.youtube.com/c/NoBoilerplate&quot; &gt;No Boilerplate YouTube Channel&lt;/a&gt; have been really informative&lt;/p&gt;
&lt;h2&gt;Frameworks&lt;/h2&gt;
&lt;p&gt;The current version of my website is built using &lt;a href=&quot;https://www.11ty.dev&quot; &gt;11ty&lt;/a&gt; which is a static site generator which uses Javascript and templates for generating HTML from a variety of data sources - in my case just JSON and Markdown files&lt;/p&gt;
&lt;p&gt;A lot of the professional work I do revolves around the React and React-Native ecosystem, but I&amp;#39;ve made some changes to my stack for personal projects due to the overhead that comes with using React&lt;/p&gt;
&lt;p&gt;For now I&amp;#39;m using 11ty for my website as well as &lt;a href=&quot;https://gohugo.io/&quot; &gt;Hugo&lt;/a&gt; for some smaller projects&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve moved on from Gatsby for my site due to the slow build times as a static site builder - and the unnecessary complexity of graphql for this purpose along with the overall burden of node modules that comes with it&lt;/p&gt;
&lt;p&gt;For other projects I&amp;#39;d like to give the &lt;a href=&quot;https://remix.run&quot; &gt;Remix Framework&lt;/a&gt; a shot for full stack apps. Remix is a full stack framework for building React applications with a pretty cool looking data fetching and project structure&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve also been playing around with &lt;a href=&quot;https://tauri.app/&quot; &gt;Tauri&lt;/a&gt; for building desktop applications. Tauri uses a Rust backend with a bring-your-own client approach and pretty much uses any client side javascript framework - I&amp;#39;m looking towards &lt;a href=&quot;https://svelte.dev/&quot; &gt;Svelte&lt;/a&gt; for this since it keeps things a lot more vanilla which is a good break from working with the other major frameworks&lt;/p&gt;
&lt;h2&gt;Code Editor&lt;/h2&gt;
&lt;p&gt;I&amp;#39;m back to VSCode after a short stint with &lt;a href=&quot;http://neovim.io&quot; &gt;NeoVim&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My reasons for leaving NeoVim were mostly due to the amount of setup when switching devices as well as the issues I experienced on Windows where configuration management was a bit inconsistent as well as the dependency management for some plugins became a lot of admin. Even preconfigured solutions like &lt;a href=&quot;https://github.com/LunarVim/LunarVim&quot; &gt;LunarVim&lt;/a&gt; and &lt;a href=&quot;https://github.com/AstroNvim/AstroNvim&quot; &gt;AstroNvim&lt;/a&gt; didn&amp;#39;t work well due to lots of compat issues on Windows&lt;/p&gt;
&lt;p&gt;As far as VSCode is concerned, some things I&amp;#39;ve been using are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.dev/&quot; &gt;The GitHub Online Editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The GitHub Colorblind Theme (GitHub.github-vscode-theme)&lt;/li&gt;
&lt;li&gt;Code Spell Checker Extension (streetsidesoftware.code-spell-checker)&lt;/li&gt;
&lt;li&gt;GitLens Extension (eamodio.gitlens)&lt;/li&gt;
&lt;li&gt;Hex Editor (ms-vscode.hexeditor)&lt;/li&gt;
&lt;li&gt;Rust Analyzer Extension (rust-lang.rust-analyzer)&lt;/li&gt;
&lt;li&gt;Fix Extension (withfig.fig)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Terminal&lt;/h2&gt;
&lt;p&gt;Some terminal tools I&amp;#39;ve been enjoying recently are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://hyper.is&quot; &gt;Hyper&lt;/a&gt; - An alternative terminal that&amp;#39;s so far been less sluggish and more customizable than the Windows Terminal application&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fig.io&quot; &gt;Fig&lt;/a&gt; - Provides autocomplete for commands and integrates with loads of CLI tools to provide detailed suggestions and documentations&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://nushell.sh&quot; &gt;NuShell&lt;/a&gt; - A shell that works with the idea of command output as data that can be manipulated and transformed which adds a lot of cool data processing functionality on top of your normal shell comands&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>A Simple JSON Backed Database in Typescript</title><link>https://nabeelvalley.co.za/blog/2022/06-07/typescript-json-database.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/06-07/typescript-json-database.html</guid><description>Create a simple database that&#39;s backed to a JSON file using Typescript and Node.js</description><pubDate>Wed, 06 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;A Simple JSON Backed Database in Typescript&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Define the database&lt;/h2&gt;
&lt;p&gt;The database is defined as a class which has an in-memory store &lt;code&gt;data&lt;/code&gt; and a &lt;code&gt;persist&lt;/code&gt; method that allows for persisting the database to a file as well as content when an instance is created from an existing JSON file&lt;/p&gt;
&lt;p&gt;The code for the database can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { existsSync, readFileSync, writeFileSync } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;fs&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Database&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; dbPath&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;initial&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;load&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(initial)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; update&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.data, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;data })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  public&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; commit&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;persist&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  private&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; persist&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    writeFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.dbPath, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  private&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; read&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;readFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.dbPath).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  private&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; load&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;initial&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;existsSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.dbPath)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;persist&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(initial)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; current&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;read&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      ...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;initial,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      ...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;current,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Usage&lt;/h3&gt;
&lt;p&gt;The database can be used by creating an instance and modifying the data in it by using the &lt;code&gt;update&lt;/code&gt; method, and can be written to a file using the &lt;code&gt;commit&lt;/code&gt; method:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Database } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./db&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  age&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DB&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  users&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; initial&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DB&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  users: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; db&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Database&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;DB&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./data.json&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, initial)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;db.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;update&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  users: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Test&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      age: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;db.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;commit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Functional Example&lt;/h3&gt;
&lt;p&gt;The above code is found in the below REPL as a runnable example:&lt;/p&gt;
&lt;iframe height=&quot;700px&quot; width=&quot;100%&quot; src=&quot;https://replit.com/@nabeelvalley/SimpleJSONDB?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Localhost HTTP Proxy with Node.js</title><link>https://nabeelvalley.co.za/blog/2022/08-03/http-proxy-node-js.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/08-03/http-proxy-node-js.html</guid><pubDate>Tue, 08 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Localhost HTTP Proxy with Node.js&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;An localhost HTTP proxy is useful for debugging and can be easily defined using Node.js by installing &lt;code&gt;http-proxy&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;yarn&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; http-proxy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then adding the following to an &lt;code&gt;index.js&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; httpProxy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;http-proxy&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; target&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;http://my-target-website.com:1234&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;httpProxy.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createProxyServer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ target }).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;listen&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8080&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which will create a server that listens on &lt;code&gt;8080&lt;/code&gt; and will proxy requests to the target&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>A type for getting properties common in all objects from a union</title><link>https://nabeelvalley.co.za/blog/2022/08-07/common-object-type.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/08-07/common-object-type.html</guid><description>Using typescript type conditions and Exclude to get keys commmon in parts of a union and an object with only common keys from that union</description><pubDate>Fri, 08 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;A type for getting properties common in all objects from a union&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Something that may come up in practice is a use for a type that allows us to enforce that an object has only the common properties for a given object&lt;/p&gt;
&lt;p&gt;For example, given the two objects below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AThing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  age&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  phone&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BThing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  businessName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  phone&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;I would like a type that contains only the things that these objects have in common, namely &lt;code&gt;phone&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;A Type for Common Object Keys&lt;/h2&gt;
&lt;p&gt;This isn&amp;#39;t something that typescript has out-of-the-box, however it can be implemented by using some type juggling&lt;/p&gt;
&lt;p&gt;First, we define a type called &lt;code&gt;CommonKeys&lt;/code&gt; which gets us all the keys which are common in the two objects&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Exclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;CommonKeys&lt;/code&gt; type makes use of a condition to check if &lt;code&gt;R&lt;/code&gt; which is the recursive type extends &lt;code&gt;T&lt;/code&gt; which is the input type. Based on this, we cut down &lt;code&gt;T&lt;/code&gt; one type at a time until there is no more object that can extend &lt;code&gt;R&lt;/code&gt;, then for an input type &lt;code&gt;T&lt;/code&gt; which is the same as &lt;code&gt;R&lt;/code&gt; (an empty object) the result of &lt;code&gt;CommonKeys&amp;lt;{}&amp;gt;&lt;/code&gt; will be &lt;code&gt;never&lt;/code&gt; since &lt;code&gt;{}&lt;/code&gt; has no keys, and will end the recursion&lt;/p&gt;
&lt;p&gt;Applying this to the above types, we get:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ABCommonKeys&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AThing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BThing&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// type ABCommonKeys = &amp;quot;email&amp;quot; | &amp;quot;phone&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And as a sanity check, we can also apply this to &lt;code&gt;{}&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Basic&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;{}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// type Basic = never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;A Type for Common Object&lt;/h2&gt;
&lt;p&gt;Next, we can use the &lt;code&gt;CommonKeys&lt;/code&gt; type defined above to create a &lt;code&gt;Common&lt;/code&gt; type which wne used with the intersection will result in a type that has all the keys common in all types from the intersection&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Common&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Pick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can apply this now to a type of &lt;code&gt;AThing | BThing&lt;/code&gt; like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ABCommonObject&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Common&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AThing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BThing&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// type ABCommonObject = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   email: string;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   phone: string | number;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can see that we have the desired result which is an object with the properties that are common between both input object types&lt;/p&gt;
&lt;h2&gt;Final Solution&lt;/h2&gt;
&lt;p&gt;We can put the code from above together into the final solution which is just the two above types:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/** Gets the keys common to any type/union of `T` */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Exclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/** Gets an object type containing all keys that exist within a type/union `T` */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Common&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Pick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;CommonKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Visualizations with React</title><link>https://nabeelvalley.co.za/blog/2022/11-02/d3-with-react.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/11-02/d3-with-react.html</guid><description>Create SVG Graphs and Visualizations in React using D3</description><pubDate>Fri, 11 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Visualizations with React&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Data Visualization with D3 and React&lt;/h2&gt;
&lt;p&gt;React is a library for building reactive user interfaces using JavaScript (or Typescript) and D3 (short for &lt;em&gt;Data-Driven Documents&lt;/em&gt;) is a set of libraries for working with visualizations based on data&lt;/p&gt;
&lt;p&gt;Before getting started, I would recommend familiarity with SVG, React, and D3&lt;/p&gt;
&lt;p&gt;Some good references for SVG are on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial&quot; &gt;MDN SVG Docs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A good place to start for React would be the &lt;a href=&quot;https://reactjs.org/&quot; &gt;React Docs&lt;/a&gt; or &lt;a href=&quot;/docs/react/complete-react.md&quot; &gt;my React Notes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And lastly, the &lt;a href=&quot;https://github.com/d3/d3/wiki&quot; &gt;D3 Docs&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Getting Stared&lt;/h3&gt;
&lt;p&gt;To follow along, you will need to install &lt;a href=&quot;https://nodejs.org/en/&quot; &gt;Node.js&lt;/a&gt; and be comfortable using the terminal&lt;/p&gt;
&lt;p&gt;I&amp;#39;m going to be using a React App with TypeScript initialized with Vite as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;yarn&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; create&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; vite&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then selecting the &lt;code&gt;react-ts&lt;/code&gt; option when prompted. Next, install &lt;code&gt;d3&lt;/code&gt; from the project root with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;yarn&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;yarn&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; add&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --dev&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; @types/d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that we&amp;#39;ve got a basic project setup, we can start talking about D3&lt;/p&gt;
&lt;h3&gt;Scales (&lt;code&gt;d3-scale&lt;/code&gt;)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/d3/d3-scale&quot; &gt;&lt;code&gt;d3-scale&lt;/code&gt; Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Broadly, scales allow us to map from one set of values to another set of values,&lt;/p&gt;
&lt;p&gt;Scales in D3 are a set of tools which map a dimension of data to a visual variable. They help us go from something like &lt;code&gt;count&lt;/code&gt; in our data to something like &lt;code&gt;width&lt;/code&gt; in our rendered SVG&lt;/p&gt;
&lt;p&gt;We can create scales for a sample dataset like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Datum&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Datum&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍊&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;21&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍇&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;13&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍏&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍌&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍐&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍋&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍎&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  { name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🍉&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, count: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Also, a common thing to do when working with scales is to define margins around out image, this is done simply as an object like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; margin&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  top: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  right: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  bottom: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  left: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;35&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This just helps us simplify some position/layout things down the line&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Scales work by taking a value from the &lt;code&gt;domain&lt;/code&gt; (data space) and returning a value from &lt;code&gt;range&lt;/code&gt; (visual space):&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 600&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleLinear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// values of the data space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, width]) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// values of the visual space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// position = scale(value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Additionally, there&amp;#39;s also the &lt;code&gt;invert&lt;/code&gt; method which goes the other way - from &lt;code&gt;range&lt;/code&gt; to &lt;code&gt;domain&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// position === 30&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; x.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;invert&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;30&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// value === 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;invert&lt;/code&gt; method is useful for things like calculating a &lt;code&gt;value&lt;/code&gt; from a mouse &lt;code&gt;position&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;D3 has different Scale types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Continuous (Linear, Power, Log, Identity, Time, Radial)&lt;/li&gt;
&lt;li&gt;Sequential&lt;/li&gt;
&lt;li&gt;Diverging&lt;/li&gt;
&lt;li&gt;Quantize&lt;/li&gt;
&lt;li&gt;Quantile&lt;/li&gt;
&lt;li&gt;Threshold&lt;/li&gt;
&lt;li&gt;Ordinal (Band, Point)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Continuous Scales&lt;/h4&gt;
&lt;p&gt;These scales map continuous data to other continuous data&lt;/p&gt;
&lt;p&gt;D3 has a few different continuous scale types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linear&lt;/li&gt;
&lt;li&gt;Power&lt;/li&gt;
&lt;li&gt;Log&lt;/li&gt;
&lt;li&gt;Identity&lt;/li&gt;
&lt;li&gt;Radial&lt;/li&gt;
&lt;li&gt;Time&lt;/li&gt;
&lt;li&gt;Sequential Color&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For my purposes at the moment I&amp;#39;m going to be looking at the methods for Linear and Sequential Color scales, but the documentation explains all of the above very thoroughly and is worth a read for additional information on their usage&lt;/p&gt;
&lt;h5&gt;Linear&lt;/h5&gt;
&lt;p&gt;We can use a &lt;code&gt;linear&lt;/code&gt; scale in the fruit example for mapping count to an x width:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; maxX&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.count) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleLinear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, maxX])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.left, width &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.right])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If we don&amp;#39;t want the custom &lt;code&gt;domain&lt;/code&gt; to &lt;code&gt;range&lt;/code&gt; interpolation we can create a custom &lt;code&gt;interpolator&lt;/code&gt;. An &lt;code&gt;interpolator&lt;/code&gt; is a function that takes a value from the &lt;code&gt;domain&lt;/code&gt; and returns the resulting &lt;code&gt;range&lt;/code&gt; value&lt;/p&gt;
&lt;p&gt;D3 has a few different &lt;code&gt;interpolators&lt;/code&gt; included for tasks such as interpolating colors or rounding values&lt;/p&gt;
&lt;p&gt;We can create a custom color domain to interpolate over and use the &lt;code&gt;interpolateHsl&lt;/code&gt; or &lt;code&gt;interpolateRgb&lt;/code&gt; functions:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; color&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleLinear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, maxX])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;pink&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lightgreen&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpolate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d3.interpolateHsl)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Sequential Color&lt;/h4&gt;
&lt;p&gt;If for some reason we want to use the pre-included color scales&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;scaleSequential&lt;/code&gt; scale is a method that allows us to map to a &lt;code&gt;color&lt;/code&gt; range using an &lt;code&gt;interpolator&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;D3 has a few different interpolators we can use with this function like &lt;code&gt;d3.interpolatePurples&lt;/code&gt;, &lt;code&gt;d3.interpolateRainbow&lt;/code&gt; or &lt;code&gt;d3.interpolateCool&lt;/code&gt; among others which look quite nice&lt;/p&gt;
&lt;p&gt;We can create a color scale using the &lt;code&gt;d3.interpolatePurples&lt;/code&gt; which will map the data to a scale of purples:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; color&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleSequential&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, maxX])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpolator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d3.interpolatePurples)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;These can be used instead of the &lt;code&gt;scaleLinear&lt;/code&gt; with &lt;code&gt;interpolateHsl&lt;/code&gt; for example above but to provide a pre-calibrated color scale&lt;/p&gt;
&lt;h4&gt;Ordinal Scales&lt;/h4&gt;
&lt;p&gt;Ordinal scales have a discrete domain and range and are used for the mapping of discrete data. These are a good fit for mapping a scale with categorical data. D3 offers us the following scales:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Band Scale&lt;/li&gt;
&lt;li&gt;Point Scale&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Band Scale&lt;/h5&gt;
&lt;p&gt;A Band Scale is a type of Ordinal Scale where the output &lt;code&gt;range&lt;/code&gt; is continuous and numeric&lt;/p&gt;
&lt;p&gt;We can create a mapping for where each of our labels should be positioned with &lt;code&gt;scaleBand&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; names&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleBand&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(names)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.top, height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The domain can be any size array, unlike in the case of continuous scales where the are usually start and end values&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Building a Bar Graph&lt;/h3&gt;
&lt;p&gt;When creating visuals with D3 there are a few different ways we can output to SVG data. D3 provides us with some methods for creating shapes and elements programmatically via a builder pattern - similar to how we create scales.&lt;/p&gt;
&lt;p&gt;However, there are also cases where we would want to define out SVG elements manually, such as when working with React so that the react renderer can handle the rendering of the SVG elements and we can manage our DOM structure in a way that&amp;#39;s a bit more representative of the way we work in React&lt;/p&gt;
&lt;h4&gt;The SVG Root&lt;/h4&gt;
&lt;p&gt;Every SVG image has to have an &lt;code&gt;svg&lt;/code&gt; root element. To help ensure that this root scales correctly we also use it with a &lt;code&gt;viewBox&lt;/code&gt; attribute which specifies which portion of the SVG is visible since the contents can go outside of the bounds of the View Box and we may not want to display this overflow content by default&lt;/p&gt;
&lt;p&gt;Using the definitions for &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; from before we can get the &lt;code&gt;viewBox&lt;/code&gt; for the SVG we&amp;#39;re trying to render like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `0 ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;top&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;width&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;top&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then, using that value in the &lt;code&gt;svg&lt;/code&gt; element:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/* we will render the graph in here */&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At this point we don&amp;#39;t really have anything in the SVG, next up we&amp;#39;ll do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add Bars to the SVG&lt;/li&gt;
&lt;li&gt;Add Y Labels to the SVG&lt;/li&gt;
&lt;li&gt;Add X Labels to the SVG&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Bars&lt;/h4&gt;
&lt;p&gt;We can create Bars using the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; bars&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;rect&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.count)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.count) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We make use of the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; functions which help us get the positions for the &lt;code&gt;rect&lt;/code&gt; as well as &lt;code&gt;y.bandWidth()&lt;/code&gt; and &lt;code&gt;x(d.count)&lt;/code&gt; to &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; for the element&lt;/p&gt;
&lt;p&gt;We can then add that into the SVG using:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;bars&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At this point, the resulting SVG will look like this:&lt;/p&gt;
&lt;svg viewbox=&quot;0 20 600 380&quot; &gt;
  &lt;g&gt;
    &lt;rect fill=&quot;rgb(38, 165, 219)&quot; y=&quot;26&quot; x=&quot;35&quot; width=&quot;208&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(68, 121, 223)&quot; y=&quot;70&quot; x=&quot;35&quot; width=&quot;130&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(175, 240, 91)&quot; y=&quot;114&quot; x=&quot;35&quot; width=&quot;545&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(97, 83, 199)&quot; y=&quot;158&quot; x=&quot;35&quot; width=&quot;52&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(32, 226, 157)&quot; y=&quot;202&quot; x=&quot;35&quot; width=&quot;337&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;246&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;290&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(88, 95, 210)&quot; y=&quot;334&quot; x=&quot;35&quot; width=&quot;78&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
  &lt;/g&gt;
&lt;/svg&gt;&lt;h4&gt;Y Labels&lt;/h4&gt;
&lt;p&gt;Next, using similar concepts as above, we can add the Y Labels:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; yLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.35em&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;d.name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can add this into the SVG, and also wrapping the element in a &lt;code&gt;g&lt;/code&gt; with a some basic text alignment and translation for positioning it correctly:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;steelblue&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`translate(${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;left&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;})`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;bars&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The state of the SVG at this point is:&lt;/p&gt;
&lt;svg viewbox=&quot;0 20 600 380&quot; &gt;
  &lt;g fill=&quot;steelblue&quot; text-anchor=&quot;end&quot; transform=&quot;translate(30, 20)&quot; &gt;
    &lt;text y=&quot;26&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍏&lt;/text&gt;
    &lt;text y=&quot;70&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍌&lt;/text&gt;
    &lt;text y=&quot;114&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍊&lt;/text&gt;
    &lt;text y=&quot;158&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍋&lt;/text&gt;
    &lt;text y=&quot;202&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍇&lt;/text&gt;
    &lt;text y=&quot;246&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍎&lt;/text&gt;
    &lt;text y=&quot;290&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍉&lt;/text&gt;
    &lt;text y=&quot;334&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍐&lt;/text&gt;
  &lt;/g&gt;
  &lt;g&gt;
    &lt;rect fill=&quot;rgb(38, 165, 219)&quot; y=&quot;26&quot; x=&quot;35&quot; width=&quot;208&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(68, 121, 223)&quot; y=&quot;70&quot; x=&quot;35&quot; width=&quot;130&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(175, 240, 91)&quot; y=&quot;114&quot; x=&quot;35&quot; width=&quot;545&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(97, 83, 199)&quot; y=&quot;158&quot; x=&quot;35&quot; width=&quot;52&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(32, 226, 157)&quot; y=&quot;202&quot; x=&quot;35&quot; width=&quot;337&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;246&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;290&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(88, 95, 210)&quot; y=&quot;334&quot; x=&quot;35&quot; width=&quot;78&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
  &lt;/g&gt;
&lt;/svg&gt;&lt;h4&gt;X Labels&lt;/h4&gt;
&lt;p&gt;Next, we can add the X Labels over each &lt;code&gt;rect&lt;/code&gt; using:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; xLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.count)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.35em&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;d.count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the resulting code looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;steelblue&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`translate(${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;left&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;})`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;bars&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;white&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`translate(-6, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;})`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;xLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the final SVG:&lt;/p&gt;
&lt;svg viewbox=&quot;0 20 600 380&quot; &gt;
  &lt;g fill=&quot;steelblue&quot; text-anchor=&quot;end&quot; transform=&quot;translate(30, 20)&quot; &gt;
    &lt;text y=&quot;26&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍏&lt;/text&gt;
    &lt;text y=&quot;70&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍌&lt;/text&gt;
    &lt;text y=&quot;114&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍊&lt;/text&gt;
    &lt;text y=&quot;158&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍋&lt;/text&gt;
    &lt;text y=&quot;202&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍇&lt;/text&gt;
    &lt;text y=&quot;246&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍎&lt;/text&gt;
    &lt;text y=&quot;290&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍉&lt;/text&gt;
    &lt;text y=&quot;334&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍐&lt;/text&gt;
  &lt;/g&gt;
  &lt;g&gt;
    &lt;rect fill=&quot;rgb(38, 165, 219)&quot; y=&quot;26&quot; x=&quot;35&quot; width=&quot;208&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(68, 121, 223)&quot; y=&quot;70&quot; x=&quot;35&quot; width=&quot;130&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(175, 240, 91)&quot; y=&quot;114&quot; x=&quot;35&quot; width=&quot;545&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(97, 83, 199)&quot; y=&quot;158&quot; x=&quot;35&quot; width=&quot;52&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(32, 226, 157)&quot; y=&quot;202&quot; x=&quot;35&quot; width=&quot;337&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;246&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;290&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(88, 95, 210)&quot; y=&quot;334&quot; x=&quot;35&quot; width=&quot;78&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
  &lt;/g&gt;
  &lt;g fill=&quot;white&quot; text-anchor=&quot;end&quot; transform=&quot;translate(-6, 20)&quot; &gt;
    &lt;text y=&quot;26&quot; x=&quot;243&quot; dy=&quot;0.35em&quot; &gt;8&lt;/text&gt;
    &lt;text y=&quot;70&quot; x=&quot;165&quot; dy=&quot;0.35em&quot; &gt;5&lt;/text&gt;
    &lt;text y=&quot;114&quot; x=&quot;580&quot; dy=&quot;0.35em&quot; &gt;21&lt;/text&gt;
    &lt;text y=&quot;158&quot; x=&quot;87&quot; dy=&quot;0.35em&quot; &gt;2&lt;/text&gt;
    &lt;text y=&quot;202&quot; x=&quot;372&quot; dy=&quot;0.35em&quot; &gt;13&lt;/text&gt;
    &lt;text y=&quot;246&quot; x=&quot;61&quot; dy=&quot;0.35em&quot; &gt;1&lt;/text&gt;
    &lt;text y=&quot;290&quot; x=&quot;61&quot; dy=&quot;0.35em&quot; &gt;1&lt;/text&gt;
    &lt;text y=&quot;334&quot; x=&quot;113&quot; dy=&quot;0.35em&quot; &gt;3&lt;/text&gt;
  &lt;/g&gt;
&lt;/svg&gt;&lt;h4&gt;Final Result&lt;/h4&gt;
&lt;p&gt;The code for the entire file/graph can be seen below:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Fruit.tsx&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3 &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;d3&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { data } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../data/fruit&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 600&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; margin&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  top: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  right: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  bottom: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  left: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;35&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; maxX&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.count) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleLinear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, maxX])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.left, width &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.right])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpolate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d3.interpolateRound)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; names&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.name)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleBand&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(names)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.top, height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;round&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; color&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleSequential&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, maxX])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpolator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d3.interpolateCool)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Fruit&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({}) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `0 ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;top&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;width&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;top&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; yLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.35em&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;d.name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; bars&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;rect&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.count)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.count) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; xLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.name)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.count)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.35em&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;d.count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;steelblue&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`translate(${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;left&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;})`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;bars&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;white&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`translate(-6, ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bandwidth&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;})`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;xLabels&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h4&gt;Ticks and Grid Lines&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that D3 includes a &lt;code&gt;d3-axis&lt;/code&gt; package but that doesn&amp;#39;t quite work given that we&amp;#39;re manually creating the SVG using React and not D3&amp;#39;s string-based rendering&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We may want to add Ticks and Grid Lines on the X-Axis, we can do this using the scale&amp;#39;s &lt;code&gt;ticks&lt;/code&gt; method like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; xGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; x.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;ticks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;line&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;lightgrey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.top&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;darkgrey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;middle&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then render this in the &lt;code&gt;svg&lt;/code&gt; as:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;xGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    {&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/* previous graph content */&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The result will look like this:&lt;/p&gt;
&lt;svg viewbox=&quot;0 20 600 380&quot; &gt;
  &lt;g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;35&quot; y1=&quot;20&quot; x2=&quot;35&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;35&quot; y=&quot;400&quot; &gt;0&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;87&quot; y1=&quot;20&quot; x2=&quot;87&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;87&quot; y=&quot;400&quot; &gt;2&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;139&quot; y1=&quot;20&quot; x2=&quot;139&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;139&quot; y=&quot;400&quot; &gt;4&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;191&quot; y1=&quot;20&quot; x2=&quot;191&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;191&quot; y=&quot;400&quot; &gt;6&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;243&quot; y1=&quot;20&quot; x2=&quot;243&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;243&quot; y=&quot;400&quot; &gt;8&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;295&quot; y1=&quot;20&quot; x2=&quot;295&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;295&quot; y=&quot;400&quot; &gt;10&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;346&quot; y1=&quot;20&quot; x2=&quot;346&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;346&quot; y=&quot;400&quot; &gt;12&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;398&quot; y1=&quot;20&quot; x2=&quot;398&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;398&quot; y=&quot;400&quot; &gt;14&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;450&quot; y1=&quot;20&quot; x2=&quot;450&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;450&quot; y=&quot;400&quot; &gt;16&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;502&quot; y1=&quot;20&quot; x2=&quot;502&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;502&quot; y=&quot;400&quot; &gt;18&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;554&quot; y1=&quot;20&quot; x2=&quot;554&quot; y2=&quot;380&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;554&quot; y=&quot;400&quot; &gt;20&lt;/text&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;g fill=&quot;steelblue&quot; text-anchor=&quot;end&quot; transform=&quot;translate(30, 20)&quot; &gt;
    &lt;text y=&quot;26&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍏&lt;/text&gt;
    &lt;text y=&quot;70&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍌&lt;/text&gt;
    &lt;text y=&quot;114&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍊&lt;/text&gt;
    &lt;text y=&quot;158&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍋&lt;/text&gt;
    &lt;text y=&quot;202&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍇&lt;/text&gt;
    &lt;text y=&quot;246&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍎&lt;/text&gt;
    &lt;text y=&quot;290&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍉&lt;/text&gt;
    &lt;text y=&quot;334&quot; x=&quot;0&quot; dy=&quot;0.35em&quot; &gt;🍐&lt;/text&gt;
  &lt;/g&gt;
  &lt;g&gt;
    &lt;rect fill=&quot;rgb(38, 165, 219)&quot; y=&quot;26&quot; x=&quot;35&quot; width=&quot;208&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(68, 121, 223)&quot; y=&quot;70&quot; x=&quot;35&quot; width=&quot;130&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(175, 240, 91)&quot; y=&quot;114&quot; x=&quot;35&quot; width=&quot;545&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(97, 83, 199)&quot; y=&quot;158&quot; x=&quot;35&quot; width=&quot;52&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(32, 226, 157)&quot; y=&quot;202&quot; x=&quot;35&quot; width=&quot;337&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;246&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(104, 73, 185)&quot; y=&quot;290&quot; x=&quot;35&quot; width=&quot;26&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
    &lt;rect fill=&quot;rgb(88, 95, 210)&quot; y=&quot;334&quot; x=&quot;35&quot; width=&quot;78&quot; height=&quot;40&quot; &gt;&lt;/rect&gt;
  &lt;/g&gt;
  &lt;g fill=&quot;white&quot; text-anchor=&quot;end&quot; transform=&quot;translate(-6, 20)&quot; &gt;
    &lt;text y=&quot;26&quot; x=&quot;243&quot; dy=&quot;0.35em&quot; &gt;8&lt;/text&gt;
    &lt;text y=&quot;70&quot; x=&quot;165&quot; dy=&quot;0.35em&quot; &gt;5&lt;/text&gt;
    &lt;text y=&quot;114&quot; x=&quot;580&quot; dy=&quot;0.35em&quot; &gt;21&lt;/text&gt;
    &lt;text y=&quot;158&quot; x=&quot;87&quot; dy=&quot;0.35em&quot; &gt;2&lt;/text&gt;
    &lt;text y=&quot;202&quot; x=&quot;372&quot; dy=&quot;0.35em&quot; &gt;13&lt;/text&gt;
    &lt;text y=&quot;246&quot; x=&quot;61&quot; dy=&quot;0.35em&quot; &gt;1&lt;/text&gt;
    &lt;text y=&quot;290&quot; x=&quot;61&quot; dy=&quot;0.35em&quot; &gt;1&lt;/text&gt;
    &lt;text y=&quot;334&quot; x=&quot;113&quot; dy=&quot;0.35em&quot; &gt;3&lt;/text&gt;
  &lt;/g&gt;
&lt;/svg&gt;&lt;h3&gt;Building a Line Graph&lt;/h3&gt;
&lt;p&gt;We can apply all the same as in the Bar Graph before to draw a Line Graph. The example I&amp;#39;ll be using consists of a &lt;code&gt;Datum&lt;/code&gt; as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Datum&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  date&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Date&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  temp&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Given that the X-Axis is a &lt;code&gt;DateTime&lt;/code&gt; we will need to do some additional conversions as well as formatting&lt;/p&gt;
&lt;h4&gt;Working with Domains&lt;/h4&gt;
&lt;p&gt;In the context of this graph it would also be useful to have an automatically calculated domain instead of a hardcoded one as in the previous example&lt;/p&gt;
&lt;p&gt;We can use the &lt;code&gt;d3.extent&lt;/code&gt; function to calculate a domain:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dateDomain&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;extent&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.date) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Date&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Date&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tempDomain&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;extent&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.temp).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then use this domain definitions in a &lt;code&gt;scale&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tempScale&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleLinear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tempDomain)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.top, height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpolate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d3.interpolateRound)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dateScale&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleTime&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dateDomain)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.left, width &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.right])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Create a Line&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;d3.line&lt;/code&gt; function is useful for creating a &lt;code&gt;d&lt;/code&gt; attribute for an SVG &lt;code&gt;path&lt;/code&gt; element which defines the line segments&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;line&lt;/code&gt; function requires &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; mappings. The line for the graph path can be seen as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; line&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;line&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Datum&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.date))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.temp))(data) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We also include the &lt;code&gt;Datum&lt;/code&gt; type in the above to scope down the type of &lt;code&gt;data&lt;/code&gt; allowed in the resulting function&lt;/p&gt;
&lt;h4&gt;Formatting&lt;/h4&gt;
&lt;p&gt;D3 includes functions for formatting &lt;code&gt;DateTime&lt;/code&gt;s. We can create a formatter for a &lt;code&gt;DateTime&lt;/code&gt; as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;timeFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;%Y-%m&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then use the formatter like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dateTime)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Grid Lines&lt;/h4&gt;
&lt;p&gt;We can define the X Axis and grid lines similar to how we did it previously:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; xGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dateTicks.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;line&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;lightgrey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.top&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      strokeDasharray&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;darkgrey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;middle&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the Y Axis grid lines:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; yGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tempTicks.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;line&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;lightgrey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.left&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      y2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      x2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;width &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.right&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      strokeDasharray&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;darkgrey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.left &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Final result&lt;/h4&gt;
&lt;p&gt;Using all the values that have been defined above, we can create the overall graph and grid lines like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;xGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;path&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; d&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;line&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;steelblue&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The final code can be seen below:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Temperature.tsx&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; *&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3 &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;d3&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { data, Datum } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;../data/temperature&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 600&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; margin&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  top: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  right: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;50&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  bottom: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  left: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;50&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tempDomain&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;extent&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.temp).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tempScale&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleLinear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tempDomain)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.top, height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpolate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d3.interpolateRound)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tempTicks&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tempScale.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;ticks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dateDomain&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;extent&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d.date) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Date&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Date&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dateScale&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;scaleTime&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dateDomain)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([margin.left, width &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.right])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dateTicks&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dateScale.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;ticks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;concat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dateScale.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;domain&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; line&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;line&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Datum&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.date))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.temp))(data) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; d3.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;timeFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;%Y-%m&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Temperature&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({}) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `0 0 ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;width&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; xGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dateTicks.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;line&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;lightgrey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        x1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        y1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.top&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        x2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        y2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.bottom&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        strokeDasharray&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;darkgrey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;middle&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;dateScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; yGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tempTicks.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;line&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;lightgrey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        y1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        x1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.left&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        y2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        x2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;width &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; margin.right&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        strokeDasharray&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;darkgrey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        textAnchor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;end&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tempScale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;margin.left &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;viewBox&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;xGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;yGrid&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;path&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; d&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;line&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;steelblue&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fill&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;svg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;p&gt;And the resulting SVG will then look something like this:&lt;/p&gt;
&lt;svg viewbox=&quot;0 0 600 400&quot; &gt;
  &lt;g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;156.48148148148147&quot; y1=&quot;20&quot; x2=&quot;156.48148148148147&quot; y2=&quot;380&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;156.48148148148147&quot; y=&quot;400&quot; &gt;
        2011-10
      &lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;267.5925925925926&quot; y1=&quot;20&quot; x2=&quot;267.5925925925926&quot; y2=&quot;380&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;267.5925925925926&quot; y=&quot;400&quot; &gt;
        2011-10
      &lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;378.7037037037037&quot; y1=&quot;20&quot; x2=&quot;378.7037037037037&quot; y2=&quot;380&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;378.7037037037037&quot; y=&quot;400&quot; &gt;
        2011-10
      &lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;489.81481481481484&quot; y1=&quot;20&quot; x2=&quot;489.81481481481484&quot; y2=&quot;380&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;489.81481481481484&quot; y=&quot;400&quot; &gt;
        2011-10
      &lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;50&quot; y1=&quot;20&quot; x2=&quot;50&quot; y2=&quot;380&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;50&quot; y=&quot;400&quot; &gt;2011-10&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;550&quot; y1=&quot;20&quot; x2=&quot;550&quot; y2=&quot;380&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;middle&quot; x=&quot;550&quot; y=&quot;400&quot; &gt;2011-10&lt;/text&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;32&quot; x1=&quot;50&quot; y2=&quot;32&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;32&quot; x=&quot;45&quot; &gt;62.5&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;50&quot; y1=&quot;62&quot; x2=&quot;550&quot; y2=&quot;62&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; x=&quot;45&quot; y=&quot;62&quot; &gt;62&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;92&quot; x1=&quot;50&quot; y2=&quot;92&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;92&quot; x=&quot;45&quot; &gt;61.5&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;122&quot; x1=&quot;50&quot; y2=&quot;122&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;122&quot; x=&quot;45&quot; &gt;61&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;152&quot; x1=&quot;50&quot; y2=&quot;152&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;152&quot; x=&quot;45&quot; &gt;60.5&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;50&quot; y1=&quot;182&quot; x2=&quot;550&quot; y2=&quot;182&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; x=&quot;45&quot; y=&quot;182&quot; &gt;60&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;212&quot; x1=&quot;50&quot; y2=&quot;212&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;212&quot; x=&quot;45&quot; &gt;59.5&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;242&quot; x1=&quot;50&quot; y2=&quot;242&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;242&quot; x=&quot;45&quot; &gt;59&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;272&quot; x1=&quot;50&quot; y2=&quot;272&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;272&quot; x=&quot;45&quot; &gt;58.5&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; x1=&quot;50&quot; y1=&quot;302&quot; x2=&quot;550&quot; y2=&quot;302&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; x=&quot;45&quot; y=&quot;302&quot; &gt;58&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;332&quot; x1=&quot;50&quot; y2=&quot;332&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;332&quot; x=&quot;45&quot; &gt;57.5&lt;/text&gt;
    &lt;/g&gt;
    &lt;g&gt;
      &lt;line stroke=&quot;lightgrey&quot; y1=&quot;362&quot; x1=&quot;50&quot; y2=&quot;362&quot; x2=&quot;550&quot; stroke-dasharray=&quot;4&quot; &gt;&lt;/line&gt;
      &lt;text fill=&quot;darkgrey&quot; text-anchor=&quot;end&quot; y=&quot;362&quot; x=&quot;45&quot; &gt;57&lt;/text&gt;
    &lt;/g&gt;
  &lt;/g&gt;
  &lt;path d=&quot;M50,20L105.55555555555554,188L161.11111111111111,236L216.66666666666666,254L272.22222222222223,260L327.77777777777777,362L383.3333333333333,380L438.88888888888886,374L494.4444444444444,380L550,176&quot; stroke=&quot;steelblue&quot; fill=&quot;none&quot; &gt;&lt;/path&gt;
&lt;/svg&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Expanding Bottom Navigation with CSS Transitions</title><link>https://nabeelvalley.co.za/blog/2022/13-11/svelte-expanding-nav.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/13-11/svelte-expanding-nav.html</guid><description>A bottom navigation with expanding icons using CSS Transitions and Svelte</description><pubDate>Sun, 13 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Expanding Bottom Navigation with CSS Transitions&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;So I was looking around on YouTube and came across a video about this library called &lt;code&gt;google_nav_bar&lt;/code&gt; for flutter and I really liked the idea of how it works and wanted to implement something similar in an app I&amp;#39;ve been working on&lt;/p&gt;
&lt;p&gt;The basic functionality of the of the library can be seen on &lt;a href=&quot;https://pub.dev/packages/google_nav_bar&quot; &gt;&lt;code&gt;google_nav_bar&lt;/code&gt; package page&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I thought the main challenge of this would be implementing the fade-in of the text with the expanding content section, I took a first shot with the result below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; selected &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;home&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; items &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;home&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;search&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;archive&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;settings&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; colors &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		home: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lightpink&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		search: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;violet&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		archive: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;skyblue&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		settings: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;lightgrey&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;svelte:head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; rel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://unpkg.com/mono-icons@1.0.5/iconfont/icons.css&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;svelte:head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;nav&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;wrapper&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;list&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		{#each items as item (item)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;item&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class:selected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{selected&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt; ===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; item}&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; on:click&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{()&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; (selected = item)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;				&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;icon&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;`--bg:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ${colors[item]}`}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;					&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;i&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;`mi&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; mi-${item}`}&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;				&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;				&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;					{item}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;				&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		{/each}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;nav&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.mi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		font-size&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;24&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.list&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		flex-direction&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;row&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		align-items&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;center&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		justify-content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;space-between&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 20&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.item&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		flex-direction&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;row&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		align-items&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;center&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		gap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		justify-content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex-start&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.item&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; .text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		opacity&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		overflow&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		transition&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: width &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.15&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, opacity &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.15&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.item.selected&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; .text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		opacity&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		transition&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: width &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.15&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, opacity &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.15&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0.075&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;	.icon&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		align-items&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;center&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		justify-content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;center&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--bg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		line-height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;	/* resets	 */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;	ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		margin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;	li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		margin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;		list-style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;none&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;I like the overall feel and I think the finicky bits of using the transition are done, but I&amp;#39;d still like to play around a bit more to see how close to the original library I can get it&lt;/p&gt;
&lt;p&gt;For now though, here&amp;#39;s the REPL with the current working state of the component:&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/ExpandingBottomNavItems?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Typescript Utilities</title><link>https://nabeelvalley.co.za/blog/2022/13-12/typescript-utilities.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/13-12/typescript-utilities.html</guid><description>Some general purpose utility types</description><pubDate>Tue, 13 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Typescript Utilities&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Here&amp;#39;s a collection of some utility types I&amp;#39;ve put together:&lt;/p&gt;
&lt;h2&gt;Functions&lt;/h2&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;ts-utils/functions.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Reverse } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./arrays&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * A function with defined input and output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;params&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * A function that returns a result or undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; OptionFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * A function that returns void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; VoidFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;params&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Convert a function type into an async version of that function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Parameters&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ReturnType&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create an async version of `Fn`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create an async version of `OptionFn`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncOptionFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;OptionFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create an async version of `VoidFn`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncVoidFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;VoidFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a version of a function that may either be sync or async&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Parameters&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReturnType&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ReturnType&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a version of `Fn` that may either be sync or async&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsyncFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a version of `OptionFn` that may either be sync or async&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsyncOptionFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  OptionFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a version of `VoidFn` that may either be sync or async&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsyncVoidFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SyncOrAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;VoidFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Returns a function with the arguments reversed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReverseArguments&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Parameters&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReturnType&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h2&gt;Arrays&lt;/h2&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;ts-utils/arrays.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * An array with at least 1 item in it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; NonEmptyArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Array filter type, used to filter an array via the `.filter` method&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ArrayFilter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;index&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;array&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Array map type, used to map an array via the `.map` method&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ArrayMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;U&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;index&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;array&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; U&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Array reduce type, used to reduce an array via the `.reduce` method&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ArrayReducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;U&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  previousValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; U&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  currentValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  currentIndex&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  array&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; U&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Defines a step type that may contain different data types as an array such&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * that each step adds or removes from the current input but should always&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * result in the same final object that can be validated by just verifying the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * final length assuming all steps have been validated prior&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StepsOf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Final&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Readonly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&amp;gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Final&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StepsOf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Final&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Reverses the input tuple&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; First&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Rest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;First&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Remove first value from array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Eat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Remove last value from array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; EatLast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Gets all possible indexes of A as an array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Indexes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;A&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; A&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; I&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Indexes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;I&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;I&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;length&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Gets all possible indexes of A as a union&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Index&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;A&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Indexes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;A&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Exclude the given T from Arr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ArrExclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Arr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Acc&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Arr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; F&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; F&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ArrExclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Acc&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ArrExclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Acc&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;F&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Acc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h2&gt;Objects&lt;/h2&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;ts-utils/objects.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Definition for a type guard that checks if a value is of a specific type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Guard&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TOther&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TResult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TOther&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TResult&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a type where the provided keys are optional&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; O&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the keys to make optional&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WithOptional&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;O&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Omit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;O&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Pick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;O&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a type where the provided keys are required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the keys to make required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WithRequired&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Required&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Pick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a type where all all properties and sub-properties are recursively partial unless they are&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * of the type specified in TKeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; TKeep&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; types to not make partial&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DeepPartial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TKeep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TKeep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DeepPartial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;], &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TKeep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Returns a specific subset of `keyof T`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * The resulting types can be used with utilities like `Omit` or `Pick` in a reusable manner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; keys of T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Keys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Primitive&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Symbol&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Date&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a type where all direct properties are optional if they&amp;#39;re Primitive otherwise it will be&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * a partial of the property&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; TKeep&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the types to not partialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FlatPartial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TKeep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Primitive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TKeep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Gets all keys of an object where the property at that key in the object extends a condition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Cond&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the condition that properties need to  extend&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the object with the keys of interest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ConditionalKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cond&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Cond&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the primitive keys of a given object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PrimitiveKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ConditionalKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Primitive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Pick the keys of an object where the property value is a primitive&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PickPrimitive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Pick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;PrimitiveKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Pick the keys of an object where the property value is not primitive&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ObjectKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Exclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;PrimitiveKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Join two keys using a separator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; JoinKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TSep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  P&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSep&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create an object with all keys prepended with some prefix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the type with the keys of interest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; P&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the prefix to prepend keys with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Sep&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the separator to use for nesting keys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ExpandPathsRec&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Primitive&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; JoinKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ExpandPathsRec&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;], &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;JoinKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create the resultant nested object using the given keys of the input object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the object to un-nest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; P&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the keys to keep when un-nesting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ExpandPaths&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; P&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ExpandPathsRec&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;], &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Bring all object properties to the top-level recursively&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the object to expand&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Sep&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the separator to use when expanding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Pathify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PickPrimitive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  ExpandPaths&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ObjectKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Sep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get object with only keys that are an array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PickArrays&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the keys of the object `Obj` that start with the given string `P`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; P&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the string that a key should be prefixed with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Obj&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the object from which to take the matching keys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; KeysStartingWith&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Obj&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Obj&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  `${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;P&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the keys of the object `Obj` that end with the given string `S`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; S&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the string that a key should be suffixed with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Obj&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the object from which to take the matching keys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; KeysEndingWith&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;S&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Obj&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Obj&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;S&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get a type or else a fallback if it is `never`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; F&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the fallback to use if `T extends never`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; OrElse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;F&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; F&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  * Check if two types are exactly equal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  * This is a direct copy from type-challenges:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  * https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Equal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;X&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Y&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; X&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h2&gt;Strings&lt;/h2&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;ts-utils/strings.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { NonEmptyArray, Reverse } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./arrays&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Types that can be cleanly/predictably converted into a string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Stringable&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Exclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * String type that will show suggestions but accept any string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; TSugg&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the strings that you want to appear as IDE suggestions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SuggestedStrings&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSugg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TSugg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Joins stringable members into a single, typed, string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Stringable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; El&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ...infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; El&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Stringable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; NonEmptyArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Stringable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      ?&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;El&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSep&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Join&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSep&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Rest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; El&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Split a strongly typed string into its parts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Split&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TSep&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TStr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TBase&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TStr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; El&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSep&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TBase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;El&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Split&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TSep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Rest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TStr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the chars of a strongly typed string as an array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Chars&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TStr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TBase&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TStr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; El&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&amp;#39;&amp;#39;}${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TStr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TBase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;El&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Chars&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Rest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the length of a string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TStr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Chars&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TStr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;length&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the first character of a string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; First&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; F&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; F&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the last character of a string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Last&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TStr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Chars&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TStr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get a string with the first character omitted&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Eat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; E&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; E&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h2&gt;JSON Schema&lt;/h2&gt;
&lt;p&gt;Type for inferring a simple JSON Schema into a TypeScript type. I think this will become super useful once Typescript adds support for importing JSON values as &lt;code&gt;const&lt;/code&gt;. This will mean that using the schema would be something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// currently the `const` part doesn&amp;#39;t exist, but would be super cool if we could get here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; schema &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./my-schema.json&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;json&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, const: true };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MySchema&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FromJSONSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; schema&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The open issue that would make the above possible is this: &lt;a href=&quot;https://github.com/microsoft/TypeScript/issues/32063&quot; &gt;https://github.com/microsoft/TypeScript/issues/32063&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&amp;#39;s relatively trivial to implement some kind of pre-build script that could do this for all JSON schemas but I think it&amp;#39;s worth waiting till the TS part of this solution exists because it would be great to be able to infer this statically&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;ts-utils/json-schema.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Relevant schema structure for inferring type definition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PartialJSONSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Properties&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;object&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  properties&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  required&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TypeMap&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TypeMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TypeMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Properties&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TypeMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Create a type where the provided keys are required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the base type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; R&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the keys to make required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WithRequired&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Required&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Pick&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;R&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Keys that have been defaulted by the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DefaultedKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;][&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * A field is required if its default value is in the list of required keys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Structure&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PartialJSONSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WithRequired&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;properties&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TypeMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;properties&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;][&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;][&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  DefaultedKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;properties&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Extracts inner resultant type to make IDE inferrence/display better&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Simplify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KeyType&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KeyType&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Get the typescript type inferred by a JSON Schema&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FromJSONSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PartialJSONSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Simplify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;required&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;properties&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WithRequired&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Structure&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;required&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;][&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Structure&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Podcast and RSS Reader App Design</title><link>https://nabeelvalley.co.za/blog/2022/14-12/rss-podcast-app-design.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/14-12/rss-podcast-app-design.html</guid><description>A design study in building an RSS and Podcasting App in Figma with light and dark mode</description><pubDate>Wed, 14 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Podcast and RSS Reader App Design&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I&amp;#39;ve been developing an app for reading RSS feeds and listening to podcasts for personal use recently, and I finally had some inspiration as far as the design goes. Though it&amp;#39;s ever-changing, here&amp;#39;s a preview of the design at this point&lt;/p&gt;
&lt;p&gt;The app is meant to provide a reading space for RSS feeds as well as allow a user to bookmark articles and tweets for later reading. In addition, it provides a way to listen to podcasts while browsing other content that&amp;#39;s been added in a way that feels consistent and easy to use across all platforms&lt;/p&gt;
&lt;h2&gt;Mobile&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve tried to remove anything that&amp;#39;s not absolutely essential from the overall app with the goal of preventing clutter on the mobile app. In order to do this I&amp;#39;ve made the bottom navigation something that adapts and shows the user relevant actions based on the screen they&amp;#39;re on as opposed to providing a combination of local and global menus as is normally seen in mobile apps&lt;/p&gt;
&lt;p&gt;For the navigation I&amp;#39;m liking the idea of a static bottom navigation that transforms and adapts as the user moves through the app - this is a decision that&amp;#39;s persisted with the desktop design as well because of how it aids in delivering a cohesive cross-platform experience&lt;/p&gt;
&lt;h3&gt;Light&lt;/h3&gt;
&lt;p&gt;For the light theme I&amp;#39;ve settled on a warm-ish background to link up with the idea of &amp;quot;highlighting&amp;quot; when reading as one might do on paper&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.8661899897854954&quot; orientation=&quot;horizontal&quot; alt=&quot;mobile-light&quot; src=&quot;/optimized-images/public/content/blog/2022/14-12/mobile-light.webp&quot; &gt;&lt;/p&gt;
&lt;h3&gt;Dark&lt;/h3&gt;
&lt;p&gt;For the dark color scheme I wanted to bring something interesting to the color palette since the typical &amp;quot;black&amp;quot; style was feeling boring. I figured color was a way to add some interest to the relatively text-heavy UI and the green was chosen for the feeling of comfort it brings which should bring a softer feel for reading&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.8661899897854954&quot; orientation=&quot;horizontal&quot; alt=&quot;mobile-dark&quot; src=&quot;/optimized-images/public/content/blog/2022/14-12/mobile-dark.webp&quot; &gt;&lt;/p&gt;
&lt;h2&gt;Desktop&lt;/h2&gt;
&lt;p&gt;For the desktop view my focus was to keep things pretty minimal and reduce the visual noise, focusing on the reader experience while being consistent with the mobile view, offering some simple style and layout modifications to better make use of the available space&lt;/p&gt;
&lt;p&gt;As far as the inbox view goes, there are some simple tabs at the top that allow switching between the different article types as in the mobile case but aside from some spacing and font size tweaks everything else is pretty much aligned to the mobile style&lt;/p&gt;
&lt;p&gt;For the article view I&amp;#39;m taking advantage of the added space in the bottom to add some of the actions that are at the top of the screen in the mobile view - this helps make better use of the space and keep the reading canvas clean as well as isolate actions into a single place which should make it easier to navigate around the app using a mouse&lt;/p&gt;
&lt;h3&gt;Light&lt;/h3&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;0.7789079229122056&quot; orientation=&quot;vertical&quot; alt=&quot;desktop-light&quot; src=&quot;/optimized-images/public/content/blog/2022/14-12/desktop-light.webp&quot; &gt;&lt;/p&gt;
&lt;h3&gt;Dark&lt;/h3&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;0.7789079229122056&quot; orientation=&quot;vertical&quot; alt=&quot;desktop-dark&quot; src=&quot;/optimized-images/public/content/blog/2022/14-12/desktop-dark.webp&quot; &gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Smooth Bottom Navigator with Secondary Actions</title><link>https://nabeelvalley.co.za/blog/2022/15-12/smooth-bottom-nav-with-actions.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/15-12/smooth-bottom-nav-with-actions.html</guid><description>A Smooth Bottom Navigator using CSS Transitions and Svelte</description><pubDate>Thu, 15 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Smooth Bottom Navigator with Secondary Actions&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Not dissimilar from my previous post on the &lt;a href=&quot;/blog/2022/13-11/svelte-expanding-nav&quot; &gt;expanding bottom nav&lt;/a&gt; this expands on the idea of animating between states in the navigator in a more global way, this version makes use of a similar animation/transition pattern but does so by modifying the heights as well as the absolute positioning of different components&lt;/p&gt;
&lt;p&gt;The implementation below takes the overall concept to the simplest possible state, however some refinements that can still be made include being responsive to the size of the additional content as well as doing a more accurate calculation on how large the sliding tab should be and how it&amp;#39;s placed&lt;/p&gt;
&lt;p&gt;The values for the padding/positions are very hardcoded, but in practice you&amp;#39;d likely want to make these respond to data provided and size appropriately in regards to rest of the component&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s the svelte code below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    InboxIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    HomeIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    DatabaseIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    MessageCircleIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    MicIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    MusicIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;svelte-feather-icons&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; selected &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;home&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; icons&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      id: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;home&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      icon: HomeIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      id: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;database&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      icon: DatabaseIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      id: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      icon: MessageCircleIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      id: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;mic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      icon: MicIcon,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  $&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: selectedIndex &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; icons.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findIndex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; item.id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; selected);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  $&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: expanded &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; selected &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;mic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;{selected}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;wrapper&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;background&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class:expanded&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class:collapsed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{!expanded}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;slider&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;      style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--left: {(selectedIndex / icons.length) * 100}%;--right: {((selectedIndex+1) / icons.length) * 100}%;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;    /&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class:expanded&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class:collapsed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{!expanded}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;MusicIcon&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Recording: 00:01:23&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;items&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {#each icons as icon}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;item&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        on:click&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{()&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; (selected = icon.id)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        on:keypress={console.log}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;svelte:component&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{icon.icon}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {/each}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; global&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* uses fixed postion in order to lock it to lock the component to the bototom of the screen */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .wrapper&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;fixed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;vw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* ensure the background and items are all placed the same since they need to overlap	 */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .items&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .background&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;absolute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    max-width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;80&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;vw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    margin-left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;auto&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    margin-right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;auto&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .background&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    border&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;solid&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; black&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    border-radius&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;16&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;white&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;52&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: height &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;300&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ease-in-out&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .background.collapsed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition-delay&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;150&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .background.expanded&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition-delay&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    overflow&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    flex-direction&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;row&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    gap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;16&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;24&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    opacity&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 40&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;all&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 300&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ease-in-out&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .content.collapsed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    opacity&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 40&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition-delay&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .content.expanded&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;24&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    opacity&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition-delay&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;150&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .content&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt; p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    margin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .slider&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;absolute&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;calc&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 6&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: va(--left);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;6&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;40&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;calc&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 12&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    border-radius&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;12&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;#87b5eb70&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transition&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;left&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 300&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ease-in-out&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .items&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    flex-direction&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;row&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    justify-content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;space-around&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;40&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* set the icon color	 */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .item&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;black&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* select a better default font */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  *&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    font-family&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Arial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;Helvetica&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;sans-serif&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    margin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the current version of the component can be seen here:&lt;/p&gt;
&lt;iframe height=&quot;400px&quot; width=&quot;100%&quot; src=&quot;https://repl.it/@nabeelvalley/AnimatedBottomNav?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Using React.memo for Controlling Component Rendering</title><link>https://nabeelvalley.co.za/blog/2022/16-08/react-memo-top-level-api.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/16-08/react-memo-top-level-api.html</guid><description>Using the react top-level API for debouncing and selectively rendering a component for better performance</description><pubDate>Tue, 16 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Using React.memo for Controlling Component Rendering&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;React Top Level API&lt;/h2&gt;
&lt;p&gt;The React library contains some functions at it&amp;#39;s top level scope. Amongst these are the built-in hooks (like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, etc.) as well as some other functions for manipulating React Elements directly - which I&amp;#39;ve covered in a previous post on &lt;a href=&quot;../01-03/react-top-level-api.md&quot; &gt;The React Top Level API&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Component Rendering&lt;/h2&gt;
&lt;p&gt;By default, React will trigger a component render whenever there is a change to its &lt;code&gt;state&lt;/code&gt; or &lt;code&gt;props&lt;/code&gt;. &lt;code&gt;React.memo&lt;/code&gt; allows us to take control of the &lt;code&gt;props&lt;/code&gt; triggered render by giving us a way to look into the prop-change process&lt;/p&gt;
&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt; is a higher order component (HOC) that allows us to wrap a component and control whether or not it is updated/re-rendered by defining a function that tells react whether or not it&amp;#39;s props are different - and effectively whether this should trigger a new render&lt;/p&gt;
&lt;p&gt;Doing the above is useful for complex components that don&amp;#39;t necessarily need to be rendered every time their props are changed&lt;/p&gt;
&lt;h2&gt;API Definition&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://reactjs.org/docs/react-api.html#reactmemo&quot; &gt;The React Docs&lt;/a&gt; give us the following example for the &lt;code&gt;React.memo&lt;/code&gt; HOC:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;jsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; MyComponent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;props&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* render using props */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; areEqual&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;prevProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;nextProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  return true if passing nextProps to render would return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  the same result as passing prevProps to render,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  otherwise return false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; MyComponentMemo&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;memo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(MyComponent, areEqual)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The component &lt;code&gt;MyComponent&lt;/code&gt; will be rendered whenever props are changed, however, using &lt;code&gt;React.memo&lt;/code&gt; lets us define a function called &lt;code&gt;areEqual&lt;/code&gt; that we can can use to tell &lt;code&gt;React.memo&lt;/code&gt; whether or not the new props would render a different result to the old props&lt;/p&gt;
&lt;p&gt;We can then use &lt;code&gt;MyComponentMemo&lt;/code&gt; in place of &lt;code&gt;MyComponent&lt;/code&gt; to take control of when the component is rendered&lt;/p&gt;
&lt;h2&gt;Rendering On a Specific Type of Change&lt;/h2&gt;
&lt;p&gt;Say we have the specific component &lt;code&gt;TimeDisplay&lt;/code&gt; which shows the time that&amp;#39;s being passed into it from &lt;code&gt;App&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./App.css&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React, { useState, useEffect } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TimeDisplayProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  time&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; TimeDisplay&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;FC&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TimeDisplayProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; display&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Date&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(time).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;{&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;display&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; App&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;setTime&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; useState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  useEffect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; handle&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      setTime&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      clearInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }, [])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;TimeDisplay&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; time&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;TimeDisplay&lt;/code&gt; component in our case only displays time to the second, so any millisecond-level changes don&amp;#39;t matter to the component and so we can save on those renders by checking if the difference in &lt;code&gt;time&lt;/code&gt; is similar to the previous render&amp;#39;s &lt;code&gt;time&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s assume for our purpose that it&amp;#39;s acceptable for the time to be delayed by about 5 seconds, we then can define a function called &lt;code&gt;areTimesWithinOneSecond&lt;/code&gt; which compares the next render&amp;#39;s props with the previous and returns if they are within 5 seconds of each other:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; areTimesWithinFiveSeconds&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  prev&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TimeDisplayProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  next&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TimeDisplayProps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; diff&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; next.time &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; prev.time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; diff &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can use the above function in a &lt;code&gt;React.memo&lt;/code&gt; to define a version of the &lt;code&gt;TimeDisplay&lt;/code&gt; component which will prevent unnecessary renders:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; TimeDisplayMemo&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;memo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(TimeDisplay, areTimesWithinFiveSeconds)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And it can then be used as a drop-in replacement for the &lt;code&gt;TimeDisplay&lt;/code&gt; component:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; default&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; App&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;setTime&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; useState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  useEffect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; handle&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      setTime&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      clearInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }, [])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;TimeDisplayMemo&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; time&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;From the above implementation we can see that it&amp;#39;s possible to delay rendering of a component using &lt;code&gt;React.memo&lt;/code&gt; if the component doesn&amp;#39;t need to be re-rendered, hence improving performance by decreasing the number of renders react needs to carry out&lt;/p&gt;
&lt;h2&gt;REPL&lt;/h2&gt;
&lt;p&gt;The REPL with the example above can seen below:&lt;/p&gt;
&lt;iframe height=&quot;700px&quot; width=&quot;100%&quot; src=&quot;https://replit.com/@nabeelvalley/react-memo-demo?lite=true&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://reactjs.org/docs/react-api.html#reactmemo&quot; &gt;The React Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Un-editable sections inside of a content editable</title><link>https://nabeelvalley.co.za/blog/2022/16-11/uneditable-sections-inside-of-conteneditable.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/16-11/uneditable-sections-inside-of-conteneditable.html</guid><description>Block user interactions and editing within a contenteditable or specific parts of it</description><pubDate>Wed, 16 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Un-editable sections inside of a content editable&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I was working on an &lt;a href=&quot;https://editorjs.io/&quot; &gt;EditorJS&lt;/a&gt; plugin and needed to have a way of creating a block that would restrict certain user interactions&lt;/p&gt;
&lt;p&gt;Initially, I tried to make use of event listeners to block the undesirable events, but the behavior on mobile was inconsistent and I wanted to avoid the mobile keyboard popping up as well when needed&lt;/p&gt;
&lt;p&gt;In addition to the above, I also noticed that even when blocking the events using JavaScript, though the debugger didn&amp;#39;t register the event, the user was still able to make changes to the sections being blocked&lt;/p&gt;
&lt;p&gt;The solution proved to be fairly simple, though only tested on chrome so it may not be robust.&lt;/p&gt;
&lt;p&gt;In my case, what worked was the following:&lt;/p&gt;
&lt;style&gt;
.demo-editable {
	padding: 10px;
	background-color: skyblue;
}

.demo-uneditable {
	padding: 10px;
	background-color: salmon;
}
&lt;/style&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; contenteditable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; contenteditable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    I should be uneditable, and on mobile won&amp;#39;t even trigger a keyboard popup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&quot;demo-editable&quot; contenteditable=&quot;true&quot; &gt;
  &lt;div contenteditable=&quot;false&quot; &gt;
    I should be uneditable, and on mobile won&amp;#39;t even trigger a keyboard popup
  &lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now, more generally, we can have other editable content while still having uneditable sections&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; contenteditable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  I continue to be editable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; contenteditable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    But I should be uneditable, and on mobile won&amp;#39;t even trigger a keyboard&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    popup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;div class=&quot;demo-editable&quot; contenteditable=&quot;true&quot; &gt;
  I continue to be editable  &lt;div class=&quot;demo-uneditable&quot; contenteditable=&quot;false&quot; &gt;
    But I should be uneditable, and on mobile won&amp;#39;t even trigger a keyboard popup
  &lt;/div&gt;
&lt;/div&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Binary Data and File Formats</title><link>https://nabeelvalley.co.za/blog/2022/20-08/understanding-binary-files.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/20-08/understanding-binary-files.html</guid><description>An introduction to bits, bytes, and binary file formats</description><pubDate>Sat, 20 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Binary Data and File Formats&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Computers work with data stored in binary formats. Reading and interpreting binary data is an important part of understanding file formats so their data can be read and interpreted&lt;/p&gt;
&lt;h2&gt;Bits and Bytes, and Binary&lt;/h2&gt;
&lt;p&gt;Binary files store data using bits&lt;/p&gt;
&lt;p&gt;A bit can be either a 1 or 0. When working with bit-data, it&amp;#39;s useful to group them into sets of 8, known as bytes&lt;/p&gt;
&lt;p&gt;A byte is a sequence of 8-bits which can contain a value ranging from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;255&lt;/code&gt; - these are referred to as the decimal representation&lt;/p&gt;
&lt;p&gt;Bytes consist of 8-bit, with each position representing a power of 2 from 2^0 to 2^7, as seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;0 0 0 0 0 0 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |__ 2^0 - 0 or 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | |____ 2^1 - 0 or 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | |______ 2^2 - 0 or 4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | |________ 2^3 - 0 or 8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |__________ 2^4 - 0 or 16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | |____________ 2^5 - 0 or 32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| |______________ 2^6 - 0 or 64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|________________ 2^7 - 0 or 128&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;total:                  0 to 255&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The byte above represents the value for 0, this is because all the bits have a value of 0&lt;/p&gt;
&lt;p&gt;Using the above explanation, the number 1 is represented using the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;0 0 0 0 0 0 0 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |__ 2^0 - 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | |____ 2^1 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | |______ 2^2 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | |________ 2^3 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |__________ 2^4 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | |____________ 2^5 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| |______________ 2^6 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|________________ 2^7 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;total:                  1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Where the position for 2^0 is the only bit with a value (1)&lt;/p&gt;
&lt;p&gt;Similarly, 2 is represented as:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;0 0 0 0 0 0 2 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |__ 2^0 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | |____ 2^1 - 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | |______ 2^2 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | |________ 2^3 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |__________ 2^4 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | |____________ 2^5 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| |______________ 2^6 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|________________ 2^7 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;total:                  2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Where the bit for 2^1 has a value&lt;/p&gt;
&lt;p&gt;Or the number 5 with bits 2^0 and 2^2 having a value:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;0 0 0 0 0 1 0 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |__ 2^0 - 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | |____ 2^1 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | |______ 2^2 - 4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | |________ 2^3 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |__________ 2^4 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | |____________ 2^5 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| |______________ 2^6 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|________________ 2^7 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;total:                  5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which is calculated by adding 2^0 + 2^2 = 1 + 4 = 5&lt;/p&gt;
&lt;p&gt;A larger number, like 234 is:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;1 1 1 0 1 0 1 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | | |__ 2^0 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | | |____ 2^1 - 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | | |______ 2^2 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | | |________ 2^3 - 8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |__________ 2^4 - 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | |____________ 2^5 - 32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| |______________ 2^6 - 64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|________________ 2^7 - 128&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;total:                  234&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The calculation for the above value is:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;2^1 + 2^3 + 2^5 + 2^6 + 2^7 = total = 234&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;When substituting the powers of 2:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;2 + 8 + 32 + 64 + 128 = total = 234&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The numbers discussed above are all 1-byte (8-bit) numbers, which have a range between 0 and 255, adding bits to the value will allow the representation of bigger numbers, for example, a 2-byte (16-bit) number can have a value from 0 to 65,535&lt;/p&gt;
&lt;h2&gt;Hexadecimal (Hex)&lt;/h2&gt;
&lt;p&gt;In the above example, numbers are represented in binary format (e.g. &lt;code&gt;000000020&lt;/code&gt;), or decimal format (e.g. 2)&lt;/p&gt;
&lt;p&gt;When looking at binary data, it can be a bit easier to navigate around by representing data in hexadecimal (hex) format - which represents every 4 bits as a value ranging from 0-15, so, similar to the byte example above, but instead using 4-bits:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;0 0 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | | |__ 2^0 - 0 or 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| | |____ 2^1 - 0 or 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;| |______ 2^2 - 0 or 4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;|________ 2^3 - 0 or 8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using what&amp;#39;s already been discussed, the number 12 can be represented in bits as &lt;code&gt;1100&lt;/code&gt;,&lt;/p&gt;
&lt;p&gt;Hex numbers additionally convert each of these values into a value from 0-9 or A-F, as seen in the following table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decimal&lt;/th&gt;
&lt;th&gt;Bits&lt;/th&gt;
&lt;th&gt;Hex&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0010&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0011&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0101&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0110&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0111&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1010&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;A&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1011&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1101&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;D&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1110&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;E&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1111&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Using the binary representation, a byte can be represented using 2 Hex values which are taken by using the first 4-bits as the first hex value, and the second 4-bits as the second hex value&lt;/p&gt;
&lt;p&gt;For example, the value for 234, represented as bits: &lt;code&gt;11101010&lt;/code&gt; can be split into 2 sets of 4-bits &lt;code&gt;1110 1010&lt;/code&gt;, using the table above, this becomes &lt;code&gt;EA&lt;/code&gt; in hex&lt;/p&gt;
&lt;h3&gt;Binary Files&lt;/h3&gt;
&lt;p&gt;Binary files encode data using bits, when viewing them, it&amp;#39;s convenient to view the data in them using bytes represented as hex values as was shown above&lt;/p&gt;
&lt;p&gt;Binary files usually require some knowledge of how their data is structured to correctly interpret the information. This is usually described in the specification for the file format&lt;/p&gt;
&lt;h2&gt;Text Files&lt;/h2&gt;
&lt;p&gt;Plain text files are usually in the UTF-8 or UTF-16 format - this means that they use 8-bits or 16-bits to represent each character, but there are lots of other formats that a text file can use&lt;/p&gt;
&lt;p&gt;UTF-8 data can be read by converting the binary data to text data using a table which maps the byte/hex value to the character -for the UTF-8 format, the character &amp;quot;A&amp;quot; is encoded in hex as &lt;code&gt;41&lt;/code&gt; and &amp;quot;z&amp;quot; is &lt;code&gt;7a&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The Hexadecimal representation for a text file that contains the following UTF-8 data:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Hello World!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Would be stored as a binary file which contains:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;48 65 6C 6C 6F 20 57 6F 72 6C 64 21&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Putting the hex below the text content, the hex to character mapping can be seen:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;H  e  l  l  o     W  o  r  l  d  !&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;48 65 6C 6C 6F 20 57 6F 72 6C 64 21&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Binary files can be viewed in a hex editor to see the raw binary data, but interpreting these files depends on the format used and will differ between file formats&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Computers store data using bits. Bits can be structured into sets of 8-bits, called a byte&lt;/p&gt;
&lt;p&gt;Data can be represented using bits, bytes, decimal values, or hexadecimal values&lt;/p&gt;
&lt;p&gt;Files store data using binary. Binary data can be represented as decimal or hex depending and can be viewed as whichever is appropriate&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=bin&quot; &gt;UTF-8 Character Table&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hexed.it/&quot; &gt;HexEdit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cs.cmu.edu/~fgandon/documents/lecture/uk1999/binary/HandOut.pdf&quot; &gt;Bits, Bytes, and Binary Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Virtual Machine vs Containers</title><link>https://nabeelvalley.co.za/blog/2022/20-12/vms-vs-containers-diagram.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/20-12/vms-vs-containers-diagram.html</guid><description>Diagrams Comparing Virtual Machines and Containers</description><pubDate>Tue, 20 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Virtual Machine vs Containers&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Virtual Machines&lt;/h2&gt;
&lt;p&gt;The below diagram illustrates a VM as it would traditionally be run along with it&amp;#39;s relevant applications and dependencies:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/content/blog/2022/20-12/virtual-machines.svg&quot; alt=&quot;Traditional Virtual Machine Diagram&quot; &gt;&lt;/p&gt;
&lt;h2&gt;Containers&lt;/h2&gt;
&lt;p&gt;The below diagram shows conainers running on a Container runtime in which they share dependencies as well as shows the relationship between an image and container instances&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/content/blog/2022/20-12/containers.svg&quot; alt=&quot;Containers and Images&quot; &gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Read Metadata from Images using Rust</title><link>https://nabeelvalley.co.za/blog/2022/25-08/read-image-metadata.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/25-08/read-image-metadata.html</guid><description>Using Rust to parse EXIF metadata from image files</description><pubDate>Thu, 25 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Read Metadata from Images using Rust&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;The complete Rust code discussed in this post can be found in the &lt;a href=&quot;https://github.com/nabeelvalley/exiflib&quot; &gt;exiflib GitHub repo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Image files, such as JPEG, PNG, and RAW formats from digital cameras and software, contain metadata about the image. This metadata can contain information ranging from the make and model of the camera used to the specific shooting conditions under which a picture was taken&lt;/p&gt;
&lt;p&gt;Reading this data depends on the image format used. This post looks at specifically reading metadata from images that use the Exchangeable Image File Format (EXIF) for storing metadata&lt;/p&gt;
&lt;h2&gt;The Rust Programming Language&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.rust-lang.org/&quot; &gt;Rust programming language&lt;/a&gt; is used to read and process the image files. Rust is a general-purpose programming language with an emphasis on performance and type safety&lt;/p&gt;
&lt;p&gt;While this post doesn&amp;#39;t cover the specifics of programming in Rust, any code samples are accompanied by a description of what the code does but it&amp;#39;s useful to have a basic understanding of programming for understanding exactly what the code is doing&lt;/p&gt;
&lt;p&gt;It&amp;#39;s also worth noting that this post covers a lot of bit-level processing of image files, to get a basic understanding of binary data works take a look at the previous post on &lt;a href=&quot;../20-08/understanding-binary-files&quot; &gt;Understanding Binary File Formats&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;The Exchangeable Image File Format (EXIF)&lt;/h2&gt;
&lt;p&gt;The Exchangeable Image File Format (EXIF) is based on the Tag Image File Format (TIFF) specification for storing metadata. This data is organised into Image File Directories (IFDs) within an image file&lt;/p&gt;
&lt;p&gt;The EXIF section in an image file is structured as follows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;Subsection&lt;/th&gt;
&lt;th&gt;Number of Bytes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Header&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;EXIF Marker (Exif00)&lt;/td&gt;
&lt;td&gt;6 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IFD&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Byte Order (II or MM)&lt;/td&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Magic Number (42)&lt;/td&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Data Start Location&lt;/td&gt;
&lt;td&gt;4 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Data Count&lt;/td&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Data Entries&lt;/td&gt;
&lt;td&gt;Data Count x 12 bytes/entry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Additional Data Section&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Reading EXIF Data&lt;/h2&gt;
&lt;p&gt;Reading EXIF data is done by reading the bytes in the file. The following examples will use a JPEG from a Fujifilm X-T200 as a reference, though the same concepts can be applied to understanding data from any file format that stores metadata using the EXIF structure&lt;/p&gt;
&lt;h3&gt;Under the Hood of an Image File&lt;/h3&gt;
&lt;p&gt;Below is a snippet of the Hex data for a JPEG file alongside the bytes decoded as text:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Hex Data                                           Decoded Text                       Approximate EXIF Subsections&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;FF D8 FF E1 57 FE 45 78 69 66 00 00 49 49 2A 00    . . . . W . E x i f . . I I * .    Header, Byte Order, Magic Number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;08 00 00 00 0C 00 0F 01 02 00 09 00 00 00 9E 00    . . . . . . . . . . . . . . . .    Data Count, Data Start Location&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;00 00 10 01 02 00 07 00 00 00 A8 00 00 00 12 01    . . . . . . . . . . . . . . . .    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;03 00 01 00 00 00 01 00 00 00 1A 01 05 00 01 00    . . . . . . . . . . . . . . . .    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;00 00 B0 00 00 00 1B 01 05 00 01 00 00 00 B8 00    . . . . . . . . . . . . . . . .    | Data Entries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;00 00 28 01 03 00 01 00 00 00 02 00 00 00 31 01    . . ( . . . . . . . . . . . 1 .    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;02 00 1E 00 00 00 C0 00 00 00 32 01 02 00 14 00    . . . . . . . . . . 2 . . . . .    |_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;00 00 DE 00 00 00 13 02 03 00 01 00 00 00 02 00    . . . . . . . . . . . . . . . .    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;00 00 98 82 02 00 05 00 00 00 F2 00 00 00 69 87    . . . . . . . . . . . . . . i .    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;04 00 01 00 00 00 14 01 00 00 A5 C4 07 00 1C 00    . . . . . . . . . . . . . . . .    | Additional Data Section&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;00 00 F8 00 00 00 EC 29 00 00 46 55 4A 49 46 49    . . . . . . . ) . . F U J I F I    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;4C 4D 00 00 58 2D 54 32 30 30 00 00 48 00 00 00    L M . . X - T 2 0 0 . . H . . .    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;01 00 00 00 48 00 00 00 01 00 00 00 44 69 67 69    . . . . H . . . . . . . D i g i    |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above snippet shows the hex data, in here the EXIF marker can be found on the first line - &lt;code&gt;45 78 69 66 00 00&lt;/code&gt; which decodes to &lt;code&gt;EXIF\0\&lt;/code&gt;, followed by the byte order &lt;code&gt;49 49&lt;/code&gt; - &lt;code&gt;II&lt;/code&gt; which means that the byte order for the file is Little Endian - which means that the smallest value in a sequence is the first byte - this can be used to decode &lt;code&gt;2A 00&lt;/code&gt; to &lt;code&gt;42&lt;/code&gt; if the byte order was Big endian the bytes representing &lt;code&gt;42&lt;/code&gt; would be flipped&lt;/p&gt;
&lt;p&gt;The byte order section is the most important thing to note on this first line as it tells an application how to read the data in the IFD as well as it is what any byte offsets should be calculated relative to&lt;/p&gt;
&lt;p&gt;Additionally, the data entries section and the additional data section are broadly marked off, to understand where data is located in this file&lt;/p&gt;
&lt;h3&gt;Reading a File as Bytes&lt;/h3&gt;
&lt;p&gt;Rust provides a method for reading a file in the standard library is &lt;code&gt;fs::read&lt;/code&gt; which can be used by providing it with a path to the file to read, the code for this looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; file &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; fs&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;read&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./sample.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;.unwrap()&lt;/code&gt; at the end tells rust to either get the file data or exit the program with an error if it could not read the file&lt;/p&gt;
&lt;p&gt;The result of this is a &lt;code&gt;Vec[u8]&lt;/code&gt; which means a vector (or list) of bytes - the bytes in the list are represented as integer values between 0 and 255, these are equivalent to the hex values in the snippet above&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;file&lt;/code&gt; is what is used to read the bytes from and will be the data source for reading the EXIF data&lt;/p&gt;
&lt;h3&gt;Finding the EXIF Starting Point&lt;/h3&gt;
&lt;p&gt;To find the starting point of the EXIF data we can scan through the file until we find the &lt;code&gt;Exif\0\0&lt;/code&gt; pattern, a function can be defined for searching for a pattern in a list of bytes:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_sequence_range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(bytes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;], pattern&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Option&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;usize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;windows&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(pattern&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;len&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;window&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; pattern)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; end &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; pattern&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;len&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(start&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;end)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The function above called &lt;code&gt;get_sequence_range&lt;/code&gt; searches the &lt;code&gt;bytes&lt;/code&gt; for a &lt;code&gt;pattern&lt;/code&gt;. This uses the &lt;code&gt;windows&lt;/code&gt; function in rust which creates a bunch of smaller lists and finds the &lt;code&gt;position&lt;/code&gt; where the &lt;code&gt;window&lt;/code&gt;, which is a section of bytes that&amp;#39;s the same length as the search &lt;code&gt;pattern&lt;/code&gt; and checks if the value is equal to the &lt;code&gt;pattern&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If the pattern can be found, then the function will return a range (basically, a start and end point) that goes from the &lt;code&gt;start&lt;/code&gt; of the found pattern until the &lt;code&gt;end&lt;/code&gt; of the pattern, which is simply the &lt;code&gt;start&lt;/code&gt; value plus the length of the pattern&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Option&lt;/code&gt; indicates that the function returns either a value if it finds one (denoted by &lt;code&gt;Some&lt;/code&gt;) or will return nothing if no value is found, denoted by &lt;code&gt;None&lt;/code&gt;. The above function uses the shorthand for the &lt;code&gt;None&lt;/code&gt; case which is done by placing a &lt;code&gt;?&lt;/code&gt; at the end of the check for the pattern - which will cause the function to end early if it could not find the pattern&lt;/p&gt;
&lt;p&gt;The above function for finding the starting point can be used by passing it the file&amp;#39;s bytes like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; EXIF_MARKER&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Exif&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\0\0&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;as_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; exif_range &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_sequence_range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(file, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;EXIF_MARKER&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Note that in the above function the &lt;code&gt;EXIF_MARKER&lt;/code&gt; is defined as the &lt;code&gt;Exif\0\0&lt;/code&gt; text converted to bytes, this is passed as the search pattern to the &lt;code&gt;get_sequence_range&lt;/code&gt; function. This gets the EXIF header location which is used to find the Byte order (Endian) marker&lt;/p&gt;
&lt;h3&gt;Getting the Byte Order&lt;/h3&gt;
&lt;p&gt;Once we know the location of the EXIF marker, the byte order values go from the 6th and 7th byte after the start of the marker. Since this is done using a range, this means that the range goes from 6 to 8, since the end value is not included in the range, this can be see defined below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ENDIAN_RANGE_FROM_EXIF_MARKER&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;usize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 6&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The bytes for the endian value can be found relative to the &lt;code&gt;exif_range&lt;/code&gt; like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; exif_range&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ENDIAN_RANGE_FROM_EXIF_MARKER&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;start;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bytes &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; file&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(start&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; endian_bytes &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; endian &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_endian&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian_bytes)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above makes use of a &lt;code&gt;get_endian&lt;/code&gt; function to get the byte order which can be defined as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_endian&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Option&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Endian&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; endian &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;full_bytes_string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian_bytes)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; endian&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;as_str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;MM&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Endian&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Big&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;II&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Endian&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Little&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        _ &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; None&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above function takes the bytes which start at the endian location and converts them to a string (text) value&lt;/p&gt;
&lt;p&gt;These values are then compared using a &lt;code&gt;match&lt;/code&gt;. If it is &lt;code&gt;II&lt;/code&gt; or &lt;code&gt;MM&lt;/code&gt; the function returns Big Endian (&lt;code&gt;Endian::Big&lt;/code&gt;) or Little Endian (&lt;code&gt;Endian::Little&lt;/code&gt;) respectively. If no matching value is found, then &lt;code&gt;None&lt;/code&gt; is returned instead&lt;/p&gt;
&lt;p&gt;The code above also finds the &lt;code&gt;bytes&lt;/code&gt;, which defines the file&amp;#39;s bytes but trims off all the bytes that are before the endian marker - this is important since any data in the IFD needs to be read relative to the this location&lt;/p&gt;
&lt;p&gt;Following the Endian bytes are 2 bytes which specify the Magic Number (42) as mentioned above - this can also be checked to verify the byte order of the file but is not covered in this post&lt;/p&gt;
&lt;h3&gt;Getting the IFD Data Start Location and Count&lt;/h3&gt;
&lt;p&gt;Immediately after the Magic Number is four bytes that specify where the IFD data starts, in the snippet above, these bytes are &lt;code&gt;08 00 00 00&lt;/code&gt; which convert to the value of &lt;code&gt;8&lt;/code&gt;, this informs us that the IFD data starts from 8 bytes from the Endian marker&lt;/p&gt;
&lt;p&gt;By following the offset value, the number of entries in the IFD can be found at the 8 bytes from the Endian marker, in this case, bytes &lt;code&gt;0C 00&lt;/code&gt; which convert to the value of &lt;code&gt;12&lt;/code&gt;, which indicates that there are 12 entries in the IFD&lt;/p&gt;
&lt;p&gt;The code applying the above logic can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ifd0_offset &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_ifd_offset&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;endian, ifd)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; usize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ifd0_entry_offset &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ifd0_offset &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ifd0_count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u16&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_offset_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;endian, ifd, ifd0_offset)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The function which gets the &lt;code&gt;ifd0_offset&lt;/code&gt; does the lookup of bytes from the range 4 to 8, relative to the Endian marker&lt;/p&gt;
&lt;h3&gt;Reading Entries in the IFD&lt;/h3&gt;
&lt;p&gt;As a reference example, the bytes for the first entry in the IFD above will be used to understand the data and how it&amp;#39;s stored&lt;/p&gt;
&lt;p&gt;After the bytes indicate the count, the next section consists of the entries. Each entry consists of 12 bytes and is structured like so:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Data Format&lt;/th&gt;
&lt;th&gt;Component Length&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;td&gt;2 Bytes&lt;/td&gt;
&lt;td&gt;4 Bytes&lt;/td&gt;
&lt;td&gt;4 Bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0F 01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;02 00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;09 00 00 00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9E 00 00 00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;The Tag is an identifier that specifies what the value of the entry represents&lt;/li&gt;
&lt;li&gt;The Data format states how the data should be read&lt;/li&gt;
&lt;li&gt;The Component Length states how many bytes the data for the entry consists of&lt;/li&gt;
&lt;li&gt;The data can either be the actual data, or a value that gives the offset to the data, depending on the Component Lenght&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Tag ID&lt;/h4&gt;
&lt;p&gt;Reading the Tag is done by parsing the first two bytes of an entry - This converts the value into a 16-bit unsigned integer (a positive integer)&lt;/p&gt;
&lt;p&gt;The TagID is read like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tag &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u16&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, entry)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The value of the tag is a 16-bit unsigned integer, but it&amp;#39;s more commonly represented as Hex value in the tag lookup tables, a lookup table for these can be found at the &lt;a href=&quot;https://exiftool.org/TagNames/EXIF.html&quot; &gt;EXIF Tool Tag Names Doc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The value of the tag above &lt;code&gt;0F 01&lt;/code&gt; can be converted to hex for the Little Endian notation resulting in &lt;code&gt;0x010F&lt;/code&gt;, the lookup table states that this tag identifies the &lt;code&gt;Make&lt;/code&gt; property in the Exif data&lt;/p&gt;
&lt;h4&gt;Data Format&lt;/h4&gt;
&lt;p&gt;The data stored in an entry can be of 12 different formats, each of these associated with a format value - the format value can be read by reading from byte index 2 in the entry, like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; format_value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u16&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_offset_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, entry, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The format value is a 16-bit unsigned integer, the same as the Tag, though this is used as an integer value and not hex. Each integer value maps to a specific format type, as seen in the below table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format Value&lt;/th&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Bytes per Component&lt;/th&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Unsigned Byte&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;u8&lt;/td&gt;
&lt;td&gt;8-bit positive integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ASCII String&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Text/String value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Unsigned Short&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;u16&lt;/td&gt;
&lt;td&gt;16-bit positive integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Unsigned Long&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;u32&lt;/td&gt;
&lt;td&gt;32-bit positive integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Unsigned Rational&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;u32, u32&lt;/td&gt;
&lt;td&gt;positive fraction - numerator and denominator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Signed Byte&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;i8&lt;/td&gt;
&lt;td&gt;8-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Undefined&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;[u8]&lt;/td&gt;
&lt;td&gt;list of bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Signed Short&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;i16&lt;/td&gt;
&lt;td&gt;16-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Signed Long&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;i32&lt;/td&gt;
&lt;td&gt;32-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Signed Rational&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;i32, i32&lt;/td&gt;
&lt;td&gt;fraction value - numerator and denominator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Single Float&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;f32&lt;/td&gt;
&lt;td&gt;floating point/decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Double Float&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;f64&lt;/td&gt;
&lt;td&gt;double precision floating point&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The above table is implemented in code by first defining a type that states all the possible format types:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; enum&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TagFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    UnsignedByte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    AsciiString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    UnsignedShort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    UnsignedLong&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    UnsignedRational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    SignedByte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    Undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    SignedShort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    SignedLong&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    SignedRational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    SingleFloat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    DoubleFloat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Each type of value can also be described in terms of the data type it stores as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; enum&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ExifValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    UnsignedByte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    AsciiString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    UnsignedShort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u16&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    UnsignedLong&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    UnsignedRational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    SignedByte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;i8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    Undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    SignedShort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;i16&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    SignedLong&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;i32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    SignedRational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;i32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;i32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    SingleFloat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;f32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    DoubleFloat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;f64&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Thereafter, a function to go from the given Format Value to the type of the tag being used:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_tag_format&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u16&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Option&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedByte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AsciiString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        3&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedShort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedLong&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedRational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        6&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedByte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        7&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        8&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedShort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        9&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedLong&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        10&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedRational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        11&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SingleFloat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        12&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Some&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;DoubleFloat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        _ &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; None&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;As done previously, if the correct value can&amp;#39;t be found, the function returns &lt;code&gt;None&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So, adding to the above code, the code for reading the tag value is:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; format_value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u16&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_offset_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, entry, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; format &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_tag_format&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;format_value)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Component Length&lt;/h4&gt;
&lt;p&gt;The Component length specifies the number of components for the tag format being read - for most tag formats this will be 1, however, for specific values like &lt;code&gt;AsciiString&lt;/code&gt; or &lt;code&gt;Undefined&lt;/code&gt;, this may be different in which case it specifies the length of the string or how many bytes are required respectively&lt;/p&gt;
&lt;p&gt;The value for the component length can be found by reading the relevant bytes in the entry and converting them to a 32-bit unsigned integer, starting from byte index 4, like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; component_length &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u32&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_offset_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, entry, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Data&lt;/h4&gt;
&lt;p&gt;Once the component length is known, getting the total length of the data to be read is done by multiplying the component length by the bytes per component - since different components need different amounts of data&lt;/p&gt;
&lt;p&gt;A function that gets the bytes per component for a given tag format can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_bytes_per_component&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(format&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; format {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedByte&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AsciiString&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedShort&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedLong&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedRational&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedByte&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedShort&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedLong&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedRational&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SingleFloat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;DoubleFloat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is based on the table shown previously on component formats&lt;/p&gt;
&lt;p&gt;Next, the total length can be defined as the component length multiplied by the bytes per component which can be seen in the code below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; component_length &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u32&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_offset_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, entry, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bytes_per_component &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; get_bytes_per_component&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;format);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; total_length &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; component_length &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bytes_per_component;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The data can be read from the data bytes, which start at index 8 of the entry&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; entry&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;8&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;12&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The data value must be the raw bytes because depending on the resulting length it needs to be processed differently&lt;/p&gt;
&lt;p&gt;If the &lt;code&gt;total_length&lt;/code&gt; is less than or equal to 4, the data can be read directly from the data bytes, this can be done using a function that converts a &lt;code&gt;TagFormat&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; to the relevant value as defined in the table:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parse_tag_value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    format&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    endian&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Endian&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    bytes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Option&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ExifValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    match&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; format {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedByte&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_unsigned_byte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;AsciiString&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_ascii_string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedShort&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_unsigned_short&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedLong&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_unsigned_long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;UnsignedRational&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_unsigned_rational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedByte&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_signed_byte&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedShort&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_signed_short&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedLong&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_signed_long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SignedRational&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_signed_rational&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SingleFloat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_single_float&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        TagFormat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;DoubleFloat&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parsing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bytes_to_double_float&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, bytes),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the data value can be obtained using the function above like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parse_tag_value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;format, endian, data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;However, if the &lt;code&gt;total_length&lt;/code&gt; is greater than 4, the data value needs to be read as an offset from the IFD which is then converted, again, using the &lt;code&gt;parse_tag_value&lt;/code&gt; function above&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;rs&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// the value needs to be checked at the offset and used from there&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; offset &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; u32&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from_endian_bytes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(endian, data)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (offset) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; usize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; end &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (length) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; usize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; range &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;..&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;end;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value_bytes &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(range)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parse_tag_value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;format, endian, value_bytes)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Putting all the above together, reading the tag above will give:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Data Format&lt;/th&gt;
&lt;th&gt;Component Length&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;td&gt;2 Bytes&lt;/td&gt;
&lt;td&gt;4 Bytes&lt;/td&gt;
&lt;td&gt;4 Bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0F 01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;02 00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;09 00 00 00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9E 00 00 00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x010f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ASCII String&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;FUJIFILM\0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Reading Additional Entries&lt;/h4&gt;
&lt;p&gt;Once a single entry can be read - reading additional entries follows the same pattern. Since the bytes per entry is fixed - always 12 - and the number of entries is known from the IFD count, each entry can be iterated over by going 12 bytes at a time and reading their data individually. A more detailed implementation of this as well as the rest of the code can be found on the &lt;a href=&quot;https://github.com/nabeelvalley/exiflib&quot; &gt;exiflib GitHub repo&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This post provides a basic outline on reading EXIF data from an image, as well as covers the byte structure for reading EXIF entries from an image file. There&amp;#39;s a lot more to reading EXIF data from images, but at a high level the parsing covered here should form a basic grounding in how reading this data works&lt;/p&gt;
&lt;p&gt;For further reference and inspiration take a look a the reference list at the end of this post as well as the &lt;a href=&quot;https://github.com/nabeelvalley/exiflib&quot; &gt;exiflib GitHub repo&lt;/a&gt; mentioned previously&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;Implementation details and guidance for reading metadata from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://exiftool.org/TagNames/EXIF.html&quot; &gt;EXIF Tool Tag Names&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://exif-viewer.com/&quot; &gt;EXIF Viewer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://greybeard.org.uk/exif3/&quot; &gt;Fujifilm EXIF Viewer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://people.cs.umass.edu/~liberato/courses/2018-spring-compsci365+590f/lecture-notes/05-bit-twiddling-file-formats-parsing-exif/&quot; &gt;COMPSCI 365/590F - Bit Twiddling File Formats, Parsing EXIF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.media.mit.edu/pia/Research/deepview/exif.html&quot; &gt;Description of Exif file format (MIT Media)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gvsoft.no-ip.org/exif/exif-explanation.html#ExifIFDTags&quot; &gt;Exif Explanation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://web.archive.org/web/20131019050323/http://www.exif.org/specifications.html&quot; &gt;Exif Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20190624045241if_/http://www.cipa.jp:80/std/documents/e/DC-008-Translation-2019-E.pdf&quot; &gt;TIFF Specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some reference implementations and libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.rs/rawloader/latest/rawloader/index.html&quot; &gt;rawloader docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://libopenraw.freedesktop.org/&quot; &gt;libopenraw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.rs/image/0.5.4/image/index.html&quot; &gt;rust image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Education App Design Ideas</title><link>https://nabeelvalley.co.za/blog/2022/27-09/open-education-app.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/27-09/open-education-app.html</guid><description>Some design snips for a learning app</description><pubDate>Tue, 27 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Education App Design Ideas&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;General App Overview&lt;/h2&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.0666666666666667&quot; orientation=&quot;horizontal&quot; alt=&quot;image1&quot; src=&quot;/optimized-images/public/content/blog/2022/27-09/image1.webp&quot; &gt;&lt;/p&gt;
&lt;h2&gt;Content Creation and Editing Experience&lt;/h2&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;2.0824427480916032&quot; orientation=&quot;horizontal&quot; alt=&quot;image3&quot; src=&quot;/optimized-images/public/content/blog/2022/27-09/image3.webp&quot; &gt;&lt;/p&gt;
&lt;h2&gt;Alternate Themes&lt;/h2&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.0825396825396825&quot; orientation=&quot;horizontal&quot; alt=&quot;image2&quot; src=&quot;/optimized-images/public/content/blog/2022/27-09/image2.webp&quot; &gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Type Narrowing in Typescript</title><link>https://nabeelvalley.co.za/blog/2022/31-05/type-narrowing.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2022/31-05/type-narrowing.html</guid><description>Using Type Narrowing for better handling of dynamic variables in typescript</description><pubDate>Tue, 31 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Type Narrowing in Typescript&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Type Narrowing allows us create conditions under which an object of one type can be used as if it is of another type. We usually use this in conjunction with union types to allow us to specify different handling of the types based on the resulting value&lt;/p&gt;
&lt;h2&gt;Using &lt;code&gt;typeof&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We can use the &lt;code&gt;typeof&lt;/code&gt; keyword in javascript to find out whether what type an object is. This is useful if we have an object that can take on different structures, for example&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; GetData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above example, we have a type called &lt;code&gt;GetData&lt;/code&gt; which can be either some data or a function to get data. Using this, we can can create a function which fetches data like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fetchData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;getData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; GetData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; getData &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;function&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; getData&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Using &lt;code&gt;in&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Javascript also has the &lt;code&gt;in&lt;/code&gt; operator which can be used to infer types by us checking a property of an object&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SimpleData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ComplexData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    first&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    last&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  isComplex&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AnyData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SimpleData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ComplexData&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then use the &lt;code&gt;in&lt;/code&gt; operator to check the existence of a property of an object by using it along with a key that we expect to be in one object but not another&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getComplexName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AnyData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // isComplex is the name of the key that we expect in `ComplexData` but not `SimpleData`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;isComplex&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [data.name.first, data.name.last].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Using &lt;code&gt;is&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We can use the typescript &lt;code&gt;is&lt;/code&gt; keyword to specify that the return of a boolean means that a variable satisfies a specific condition&lt;/p&gt;
&lt;p&gt;For example, we can create a function that basically does what the &lt;code&gt;in&lt;/code&gt; operator in the above function does:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isComplex&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AnyData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ComplexData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ComplexData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).isComplex&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This can be used in place of the &lt;code&gt;in&lt;/code&gt; check in the above example like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getComplexName2&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AnyData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // isComplex is the name of the key that we expect in `ComplexData` but not `SimpleData`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isComplex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [data.name.first, data.name.last].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/docs/javascript/typescript-basics&quot; &gt;My TS Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in&quot; &gt;MDN The &lt;code&gt;in&lt;/code&gt; operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof&quot; &gt;MDN The &lt;code&gt;typeof&lt;/code&gt; operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/narrowing.html&quot; &gt;TS Docs on Narrowing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Generic Object Property Formatter and Validator using Typescript</title><link>https://nabeelvalley.co.za/blog/2023/09-05/generic-transformer-typescript.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/09-05/generic-transformer-typescript.html</guid><description>A statically typed, generic method for formatting and validating javascript objects for interchange across system boundaries</description><pubDate>Tue, 09 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Generic Object Property Formatter and Validator using Typescript&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;At times there&amp;#39;s a need for transforming specific object properties from an input format to some specific output, this can be done using the following code in some generic means&lt;/p&gt;
&lt;h2&gt;The Concept of a Schema&lt;/h2&gt;
&lt;p&gt;The concept of a schema to be used for formatting some data can be defined as follows&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Primitive&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Symbol&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Date&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/** * Define a formatter that can take in a generic object type and format each entry of that object */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FormatterSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; in&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Primitive&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; // if the value is primitive then we can just transform it using a simple function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; // if it&amp;#39;s an object then it should either be a formatter schema or a transformer function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      FormatterSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;An Interpreter&lt;/h2&gt;
&lt;p&gt;The implementation of an interpreter that satisfies the above can done as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isFormatterFn&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FormatterSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; formatter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;function&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isFormatterObj&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FormatterSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Exclude&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; formatter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;object&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; interpret&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;schema&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; FormatterSchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Formatter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; keys&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Object.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;keys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(schema) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; keys.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;reduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;prev&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; keySchema&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; schema[key]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; keyVal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val[key]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isSchemaFn&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isFormatterFn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(keySchema)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (isSchemaFn) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;          ...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;prev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          [key]: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;keySchema&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(keyVal),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isSchemaObj&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isFormatterObj&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(keySchema)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (isSchemaObj) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;          ...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;prev,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          [key]: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;interpret&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(keySchema)(keyVal),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; prev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }, val)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Transformers&lt;/h2&gt;
&lt;p&gt;We can define some general transformers, for example:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; trunc&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Math.trunc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; round&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Math.round&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;len&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;slice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, len)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; trim&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;trim&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; constant&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    val&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; optional&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    val &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(val)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; formatter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  trunc,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  round,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  length,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  trim,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  constant,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  optional,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;For the sake of example we can define a data type to use&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  location&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    address&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    city&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    gps&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Bob Smithysmithson&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  location: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    city: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Somewhere secret&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    address: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;123 Secret street&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    gps: [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;123&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;456&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Using as a Transformer&lt;/h3&gt;
&lt;p&gt;We can use the above by defining the transformer and using it to transform the input data according to the defined schema&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; format&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; interpret&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  name: formatter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  location: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    city&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Home&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Away&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;includes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(val) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Other&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    gps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isValidGPS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(val) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; format&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(user)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   name: &amp;#39;Bob Smithy&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   location: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//     city: &amp;#39;Other&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//     adddtess: &amp;#39;123 Secret street&amp;#39;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//     gps: undefined,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Using as a Validator&lt;/h3&gt;
&lt;p&gt;Using the same principal as above we can use it for validaing data. Validation can be done by throwing in the transformer function&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; validate&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; interpret&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (val.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      throw&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Length too long&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// throws with Length too long&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;validate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Jack Smith&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Exploration&lt;/h2&gt;
&lt;p&gt;It may be worth taking the concept and expanding it into a more fully fledged library with a way to handle validations more simply or to provide more builtin transformers and validators but for the moment it can be stated that there are enough javascript libraries for validation and the formatter alone is likely of limited value but may be worth exploring further if gaps in the existing technology are found&lt;/p&gt;
&lt;p&gt;Regardless of the utility of the particular type above I think the concept and types give some insight into how one can build out a library as the ones discussed above&lt;/p&gt;
&lt;h2&gt;Working Example&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;A working playground with the code from here can be found at &lt;a href=&quot;https://www.typescriptlang.org/play?jsx=0&amp;amp;module=1#code/KYDwDg9gTgLgBDAnmYcAKUCWBbTNMBuqAvHAM4xYB2A5nAD5xUCu2ARsFA3GxBADbAAhlW4BlROwHcAIkJjAA3AChlcAPQAqTXB0zgAM0xVUQuAejZ5CrjAAW8uAGMRCIQGtUxuGZrATWE5wEGwAVsBO8EgoPlQAJuaWjsJOdnD+lIjBBggO8CHhkbrqyqCQsAjIqABiSTA2YqnAVgA8ACoAfHCkAN5qcADaANJw3p6IEDltALoA-ABccG3D0+kgCvFk6Fi4+ET9cBrqozn2qARC-MxeW2A7eISoZ6IA7qguoqHMFAhQImQWKDYUbwb7GOhmMg4MCCczMKiRTAQKgHOCzOAACgu-EWyyG0wAlN0unjpqj1MdMDk8AByLauAoRKJ2fwg8h2CDMfgJYB4FlcDg+RJA6ycchNKzBLhmSj-QHYMUGeGI5Goxa1EX1TiNFmtUldRgYrGXXErInEElmlQAXxUymiNTqNnaXVIxpxS3NJJUTmRP0wZA1Vi1UGqolILox-Xloqg6qd2olQhdA3GkyWZIJixjIdGWyDsfaqeAEym01dXQd6ZzNm6xFINKVCPwyJpdt9VH9gYTUAA8mFunBI9Ge-HNQ0kym02XlFnhcHawG4ABREBOK5xYAtAshovTjMdAA0cGqypbVArlRQ1Z7dYbjMibdUZWg8A7-qoNjuwHgxH6kbIJMxwXRNdWTTo5x3Z1OmJfp3S9OA+kOQ533gcYtlIftChgAA6dCMUAsCiSELYAEEoD+RAWn3ToVGQuAoB-ZgoFEdCcMYuJmCcLdOiNb8CGPcYEKQ+jnD9NCSx1ZozFIQjpOLRBpjo0TULgcYADVLkHbEFKU1RRLEzt4ADKSrDDQcAygzgwwxcZTKEAllPoqlMRMpMwyJESDMYmBmNELyDLgHDgv4w9UQM3TFjspNbJLTT+AJMLArgW1wpS-SVPEvN7Kwizu3HTgsNixB7MctKXIxNywKwzy0sOHy-MQurkOCnDQuaw5ItGT9OG-GBitK4r4sS5rUoM60MvohqWLgfinJS49sTKw5Uv6d8BGAHD+AgGhKp6qA+oJVRVMoZVBwAWXkOwcNOhF2yyqBOXiC6rvYp64nuoy4EEWh7EHDEfsWFh2E4BD3UWChqBoBDsRwsh+EwbiMQABmPH6yuUE6dn+7EIcocEYcuG6dgxDHVNQkRf3-Xjcc9WDDlJ+nkOxT6fggMBzy0v9DkjAwqEWcG6YtIWOjg7EFhF1FsTvOB4U3IwTASdE5cMYxgASbMqHgu0XwqVSazFXp+lupwkoY96zZ+mh7DN-HsDNinPzN9nOf4MLVodOAAFUyENprDioIQFTxqHLYgFxz0WAKhDiOJGLIMgQ-BM2ULwRAk9oFO4BoMAyAlgZgY4KBj0LzgyRW5QJsxrKA3izA4gAcTQMQccufPS+LphWCLwliXMS5fdZ+Acws-a+paH3OA6DERMD4P51jLb-GtuwMQARmRkbDm2iOkX5-3kKcNOBaWvuBhpAAJCAFRpY8aVIl4hEQGlphw4x12YTcyHgtE4GlxYaS9jOFAW+qIc6J0xKfYWtdLj1ybmIH+6J-6y3iKrRWZsJrWiOtXL63wxSLEnlwI2Acg7AAAQAIRCHAMQuw7CIDILQsgrYw672RFHVER8kAALENfYALx+SoF9k4HyoD6IxzjsABOAC14ACYADM1CIg+XIJQYAP5RHIXAYsAYsi5HHgACwAFYABs5d0pV1UvHLkv4F79TwVAbB61BBbR2hiKx-AYCOKytieu8gSDdS-D5CevsoDT1nqQk+lxhKogqrDK2f0uiGNqgZewj0XhwAAEQABll5-RgHwb6yIaAZNRFXKaTEZrYn6Jg7BFJchpK2C8PkTBSEIAKdtWgygfFxD8RiexBIgA&quot; &gt;The Typescript Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;iframe height=&quot;600px&quot; width=&quot;100%&quot; src=&quot;https://www.typescriptlang.org/play?jsx=0&amp;amp;module=1#code/KYDwDg9gTgLgBDAnmYcAKUCWBbTNMBuqAvHAM4xYB2A5nAD5xUCu2ARsFA3GxBADbAAhlW4BlROwHcAIkJjAA3AChlcAPQAqTXB0zgAM0xVUQuAejZ5CrjAAW8uAGMRCIQGtUxuGZrATWE5wEGwAVsBO8EgoPlQAJuaWjsJOdnD+lIjBBggO8CHhkbrqyqCQsAjIqABiSTA2YqnAVgA8ACoAfHCkAN5qcADaANJw3p6IEDltALoA-ABccG3D0+kgCvFk6Fi4+ET9cBrqozn2qARC-MxeW2A7eISoZ6IA7qguoqHMFAhQImQWKDYUbwb7GOhmMg4MCCczMKiRTAQKgHOCzOAACgu-EWyyG0wAlN0unjpqj1MdMDk8AByLauAoRKJ2fwg8h2CDMfgJYB4FlcDg+RJA6ycchNKzBLhmSj-QHYMUGeGI5Goxa1EX1TiNFmtUldRgYrGXXErInEElmlQAXxUymiNTqNnaXVIxpxS3NJJUTmRP0wZA1Vi1UGqolILox-Xloqg6qd2olQhdA3GkyWZIJixjIdGWyDsfaqeAEym01dXQd6ZzNm6xFINKVCPwyJpdt9VH9gYTUAA8mFunBI9Ge-HNQ0kym02XlFnhcHawG4ABREBOK5xYAtAshovTjMdAA0cGqypbVArlRQ1Z7dYbjMibdUZWg8A7-qoNjuwHgxH6kbIJMxwXRNdWTTo5x3Z1OmJfp3S9OA+kOQ533gcYtlIftChgAA6dCMUAsCiSELYAEEoD+RAWn3ToVGQuAoB-ZgoFEdCcMYuJmCcLdOiNb8CGPcYEKQ+jnD9NCSx1ZozFIQjpOLRBpjo0TULgcYADVLkHbEFKU1RRLEzt4ADKSrDDQcAygzgwwxcZTKEAllPoqlMRMpMwyJESDMYmBmNELyDLgHDgv4w9UQM3TFjspNbJLTT+AJMLArgW1wpS-SVPEvN7Kwizu3HTgsNixB7MctKXIxNywKwzy0sOHy-MQurkOCnDQuaw5ItGT9OG-GBitK4r4sS5rUoM60MvohqWLgfinJS49sTKw5Uv6d8BGAHD+AgGhKp6qA+oJVRVMoZVBwAWXkOwcNOhF2yyqBOXiC6rvYp64nuoy4EEWh7EHDEfsWFh2E4BD3UWChqBoBDsRwsh+EwbiMQABmPH6yuUE6dn+7EIcocEYcuG6dgxDHVNQkRf3-Xjcc9WDDlJ+nkOxT6fggMBzy0v9DkjAwqEWcG6YtIWOjg7EFhF1FsTvOB4U3IwTASdE5cMYxgASbMqHgu0XwqVSazFXp+lupwkoY96zZ+mh7DN-HsDNinPzN9nOf4MLVodOAAFUyENprDioIQFTxqHLYgFxz0WAKhDiOJGLIMgQ-BM2ULwRAk9oFO4BoMAyAlgZgY4KBj0LzgyRW5QJsxrKA3izA4gAcTQMQccufPS+LphWCLwliXMS5fdZ+Acws-a+paH3OA6DERMD4P51jLb-GtuwMQARmRkbDm2iOkX5-3kKcNOBaWvuBhpAAJCAFRpY8aVIl4hEQGlphw4x12YTcyHgtE4GlxYaS9jOFAW+qIc6J0xKfYWtdLj1ybmIH+6J-6y3iKrRWZsJrWiOtXL63wxSLEnlwI2Acg7AAAQAIRCHAMQuw7CIDILQsgrYw672RFHVER8kAALENfYALx+SoF9k4HyoD6IxzjsABOAC14ACYADM1CIg+XIJQYAP5RHIXAYsAYsi5HHgACwAFYABs5d0pV1UvHLkv4F79TwVAbB61BBbR2hiKx-AYCOKytieu8gSDdS-D5CevsoDT1nqQk+lxhKogqrDK2f0uiGNqgZewj0XhwAAEQABll5-RgHwb6yIaAZNRFXKaTEZrYn6Jg7BFJchpK2C8PkTBSEIAKdtWgygfFxD8RiexBIgA&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot; sandbox=&quot;allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals&quot; &gt;&lt;/iframe&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Interacting with Kafka with Kotlin Coroutines</title><link>https://nabeelvalley.co.za/blog/2023/11-11/interacting-with-kafka-using-kotlin.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/11-11/interacting-with-kafka-using-kotlin.html</guid><description>Producing, Consuming, and Processing Kafka Event Streams</description><pubDate>Sat, 11 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Interacting with Kafka with Kotlin Coroutines&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;The purpose of this post is to illustrate a method of interacting with Kafka using Kotlin in a functional programming style while using Kotlin coroutines for a multi-threading. We will be interacting with the &lt;a href=&quot;https://docs.confluent.io/kafka-clients/java/current/overview.html&quot; &gt;Kafka Client for Java&lt;/a&gt; and will be building a small library on top of this for the purpose of simplifying communication and handling tasks like JSON Serialization&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you would like to view the completed source code, you can take a look at the &lt;a href=&quot;https://github.com/nabeelvalley/kotlin-kafka&quot; &gt;kotlin-kafka GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Kafka&lt;/h3&gt;
&lt;p&gt;According to then &lt;a href=&quot;https://kafka.apache.org/&quot; &gt;Kafka Website&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Apache Kafka is an open-source distributed event streaming platform:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Generally we can think of Kafka as a platform that enables us to connect data producers to data.&lt;/p&gt;
&lt;p&gt;Kafka is an event platform that provides us with a few core functions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Publishing and subscribing event data&lt;/li&gt;
&lt;li&gt;Processing of events in real-time or retrospectively&lt;/li&gt;
&lt;li&gt;Storage of event streams&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From a more detailed perspective, Kafka internally handles storage of event streams, but we are given control over the means of data production, consumption, and processing via the Kafka API, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Producer API for production&lt;/li&gt;
&lt;li&gt;The Consumer API for subscription&lt;/li&gt;
&lt;li&gt;The Streams API for processing stream data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kotlin&lt;/h3&gt;
&lt;p&gt;Kotlin is a statically typed programming language built on the Java Virtual Machine that provides interop with Java code&lt;/p&gt;
&lt;h2&gt;The Code&lt;/h2&gt;
&lt;h3&gt;Config&lt;/h3&gt;
&lt;p&gt;To get some admin stuff out of the way, before you can really do any of this you will to have a &lt;code&gt;.env&lt;/code&gt; file in the project that you can load which contains some application configuration, for the purpose of our application we require the following config in this file - below is some example content&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;BOOTSTRAP_SERVERS&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;my-server-url:9092&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;SASL_JAAS_CONFIG&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;org.apache.kafka.common.security.scram.ScramLoginModule&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; required&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; username=&amp;quot;someUsername&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; password=&amp;quot;somePassword&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Additionally, we have some non-sensitive config in our &lt;code&gt;application.properties&lt;/code&gt; file in our application &lt;code&gt;resources&lt;/code&gt; folder which contains the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;resources/application.properties&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;properties&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;sasl.mechanism&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=SCRAM-SHA-256&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;security.protocol&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=SASL_SSL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;key.serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=org.apache.kafka.common.serialization.StringSerializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;key.deserializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=org.apache.kafka.common.serialization.StringDeserializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;value.serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=org.apache.kafka.common.serialization.StringSerializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;value.deserializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=org.apache.kafka.common.serialization.StringDeserializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;auto.offset.reset&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=earliest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;group.id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=$GROUP_NAME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;application.id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=example-app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we need to load this in our application to create a &lt;code&gt;Properties&lt;/code&gt; object along with all the other application config we require. We can create the Properties object using the &lt;code&gt;application.properties&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt; files as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;App.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; io.github.cdimascio.dotenv.Dotenv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.io.FileInputStream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; loadProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; props &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; resource &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ClassLoader.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getSystemResource&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;application.properties&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    println&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;File  path: ${resource.path}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    FileInputStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(resource.path).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;use&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { stream &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        props.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;load&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(stream)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dotenv &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Dotenv.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;load&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    props[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bootstrap.servers&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dotenv[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;BOOTSTRAP_SERVERS&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    props[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;sasl.jaas.config&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dotenv[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;SASL_JAAS_CONFIG&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; props&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above example uses the &lt;code&gt;io.github.cdimascio:dotenv-java:3.0.0&lt;/code&gt; package for loading the environment variables and some builtin Java utilities for loading the application properties file&lt;/p&gt;
&lt;p&gt;Next, for the purpose of using it with our library we will create a &lt;code&gt;Config&lt;/code&gt; class that wraps the properties file we defined so that we can use this a little more elegantly in our consumers. Realistically we probably should do some validation on the resulting &lt;code&gt;Properties&lt;/code&gt; that we load in but we&amp;#39;ll just keep it simple and define &lt;code&gt;Config&lt;/code&gt; as a class that contains the &lt;code&gt;properties&lt;/code&gt; as a property:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Config.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.Properties&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;open&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Config&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;internal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Working with JSON Data&lt;/h3&gt;
&lt;p&gt;An important part of what we want our client to handle is the JSON serialization and deserialization when sending data to Kafka. Sending JSON data is not a requirement of Kafka as a platform, but it&amp;#39;s the usecase that we&amp;#39;re building our library around and so is something we need to consider&lt;/p&gt;
&lt;h4&gt;Serialization&lt;/h4&gt;
&lt;p&gt;Serialization in this context refers to the process of converting our Kotlin classes into a string and back to a Kotlin class. For this discussion we will refer to a class that is able to do this bidirectional conversion as a &lt;code&gt;Serializer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can define generic representation of a serializer as a class that contains a method callsed &lt;code&gt;serialize&lt;/code&gt; that takes in data of type &lt;code&gt;T&lt;/code&gt; and returns a string, and contains a method called &lt;code&gt;deserialize&lt;/code&gt; that takes in a string and returns an object of type &lt;code&gt;T&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not that at this point we&amp;#39;re not considering that the serializer needs to return JSON. In our context a JSON serializer is just a specific implementation of the serialization concept that we have defined&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;An interface that describes the &lt;code&gt;Serializer&lt;/code&gt; we mentioned above can be seen as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Serializer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; serialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; deserialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;JSON Serialization&lt;/h4&gt;
&lt;p&gt;Given the definition of a serializer we can define a JSON serializer that uses the &lt;code&gt;kotlinx.serialization&lt;/code&gt; library and implements our &lt;code&gt;ISerializer&lt;/code&gt; as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;JsonSerializer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.serialization.KSerializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.serialization.json.Json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.serialization.serializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlin.reflect.KClass&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(type: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KClass&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(type.java) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; KSerializer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; serialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Json.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;encodeToString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(serializer, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; deserialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Json.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;decodeFromString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(serializer, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above code is a little funky since we&amp;#39;re using reflection on the actual class of the input data to define our serializer, other than we&amp;#39;re just using the &lt;code&gt;kotlinx&lt;/code&gt; serializer to handle the data transformation. The thing that matters in this context is that we are able abstract the reflection aspect of the serializer, this will help make the final interface we provide to the user for working with Kafka simpler&lt;/p&gt;
&lt;h4&gt;Serde Serializer&lt;/h4&gt;
&lt;p&gt;Now that we have defined a simple representation of a serializer that provides some interop with the Kotlin data types, we need to implement the other side of this which is a &lt;code&gt;SerdeSerializer&lt;/code&gt; which is what the Kafka Clients need to work with. The requirements of this serializer are a little different to the one we defined above. This serializer needs to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Have a separate &lt;code&gt;Serializer&lt;/code&gt; and &lt;code&gt;Deserializer&lt;/code&gt; interfaces that need to be implemented&lt;/li&gt;
&lt;li&gt;Return a &lt;code&gt;ByteArray&lt;/code&gt; instead of &lt;code&gt;String&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can define these serializers such that they can be constructed from and &lt;code&gt;ISerializer&lt;/code&gt; interface that we defined previously. This will make it possible for consumers of our library to swap our their serialization strategy to enable other usecases than the simple JSON communication we are considering&lt;/p&gt;
&lt;p&gt;As mentioned above, we need to implement a separate &lt;code&gt;Serializer&lt;/code&gt; and &lt;code&gt;Deserializer&lt;/code&gt; respecively as:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SerdeSerializer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.common.serialization.Serializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SerdeSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; serialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;?, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ByteArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;serialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toByteArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SerdeDeserializer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.common.serialization.Deserializer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SerdeDeserializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Deserializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;?&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; deserialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;?, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ByteArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;?): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;? {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; string &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data!!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;deserialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(string)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (error: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;            println&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Error Deserializing Data: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;$error&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Our implementation is a little basic and will just ignore any data that we can&amp;#39;t serialize, however depending on our usecase we may need to handle this differently&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lastly, we define the actual &lt;code&gt;Serde&lt;/code&gt; Serializer implementation using the above implementations:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Serializer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.common.serialization.Serde&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Serde&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; SerdeSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(serializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; deserializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; SerdeDeserializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(serializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;As far as serialization and deserialization goes, this should be everything we need for working with JSON data&lt;/p&gt;
&lt;h3&gt;Producing Data&lt;/h3&gt;
&lt;p&gt;Producing data is a method by which a client sends data to a Kafka topic. We can define this as a type as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, message: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Unit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, to provide a functional library interface we will want to provider application code a space in which they will be able to work with the producer that we populate without needing to create a new producer for each message we want to send&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll codify this intent as a type as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; suspend&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (send: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Unit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that we define this as a &lt;code&gt;suspend&lt;/code&gt; function that will enable users to send messages from within a coroutine context&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next, we define the type of our producer as method with a way to create a producer instance for users who may want to manage the lifecycle of the &lt;code&gt;KafkaProducer&lt;/code&gt; on their own. This however also means they lose access to the automatic serialization and deserialization that we will provide via our &lt;code&gt;producer&lt;/code&gt; method&lt;/p&gt;
&lt;p&gt;This interface is defined as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.clients.producer.KafkaProducer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     * Returns the raw producer used by Kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KafkaProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(callback: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For the purpose of our implementation we can define some functions ourside of our class that will provde the implementation we require&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;createProducer&lt;/code&gt; function, we simply provide a wrapper around the &lt;code&gt;KafkaProducer&lt;/code&gt; provided to us by the Java Kafka Client Library:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.clients.producer.KafkaProducer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.clients.producer.ProducerRecord&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.runBlocking&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    KafkaProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(properties)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For the sake of consistency, we will do the same for the concept of a &lt;code&gt;ProducerRecord&lt;/code&gt; which will be used by the produce function:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createRecord&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, message: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    ProducerRecord&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(topic, message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, the &lt;code&gt;produce&lt;/code&gt; function can be defined. The role of this function is to handle serialization of data and provide a means for a user to send data to a topic&lt;/p&gt;
&lt;p&gt;The producer will take a callback which is the context in which any usage of the &lt;code&gt;send&lt;/code&gt; function should be used before the producer is disposed:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, callback: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    createProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;use&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { producer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; send &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, message: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; payload &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;serialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; record &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createRecord&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic, payload)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            producer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(record)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        runBlocking&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;            callback&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(send)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We have also added the &lt;code&gt;properties&lt;/code&gt; and &lt;code&gt;serializer&lt;/code&gt; values as an input to the producer as this is needed by Kafka, lastly, we will define our actual &lt;code&gt;Producer&lt;/code&gt; implementation which builds on the functions we defined above&lt;/p&gt;
&lt;p&gt;Note that our &lt;code&gt;Producer&lt;/code&gt; class implements &lt;code&gt;IProducer&lt;/code&gt; and extends &lt;code&gt;Config&lt;/code&gt;, this is because we use the &lt;code&gt;Config&lt;/code&gt; class as the source of truth of the configuration to be used for our Kafka instance and we want to able to access this config&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Producer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Producer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Config&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    IProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createProducer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(callback: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(properties, serializer, callback)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At this point we have a complete implementation of a producer&lt;/p&gt;
&lt;h4&gt;Using the Producer&lt;/h4&gt;
&lt;p&gt;In our application code we can instantiate and use the producer as follows:&lt;/p&gt;
&lt;p&gt;Firstly, we need to define the type of data we are goind to send with the &lt;code&gt;@Serializable&lt;/code&gt; annotation&lt;/p&gt;
&lt;p&gt;&lt;code&gt;App.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.serialization.Serializable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;@Serializable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ProducerData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; message: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; key: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Int&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can define a function for producing data, this will require the &lt;code&gt;properties&lt;/code&gt; we loaded previously:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;App.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; instantiateAndProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Unit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ProducerData::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; producer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Producer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties, serializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    runBlocking&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        producer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;produce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { send &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; ProducerData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;            send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;my-topic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We use &lt;code&gt;runBlocking&lt;/code&gt; since our producer needs a coroutine scope in which to send data. Sending data us used within the &lt;code&gt;produce&lt;/code&gt; method in which we create some data and call the &lt;code&gt;send&lt;/code&gt; method provide by the &lt;code&gt;produce&lt;/code&gt; function&lt;/p&gt;
&lt;p&gt;An interesting to note is that we are passing the &lt;code&gt;class&lt;/code&gt; of our data to the serializer to create an instance - this is the usage of the funky reflection thing we saw previously&lt;/p&gt;
&lt;h3&gt;Consuming Data&lt;/h3&gt;
&lt;p&gt;Our code for consuming data will follow a similar pattern to what we use to consume the data in the previous section&lt;/p&gt;
&lt;p&gt;For consuming data, Kafka relies on the concept of polling for records from the part of the consumer, for our client, we will expose using the following type which defines a poll as a method that takes nothing and returns a list of data of type &lt;code&gt;T&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Poll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; List&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can define the type that defines how we want our data to be consumed. For our sake, this is a suspend function that will receive a poll method that it can call to get data&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; suspend&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (poll: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Poll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Unit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, as before, we can define an interface for a &lt;code&gt;Consumer&lt;/code&gt; in which we have a method to create a &lt;code&gt;KafkaConsumer&lt;/code&gt; and a method for actually consuming the data. In the case of consuming we need a list of topics to read from as well as the polling frequency duration.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.runBlocking&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.clients.consumer.ConsumerRecord&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.clients.consumer.KafkaConsumer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.time.Duration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     * Returns the raw consumer used by Kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KafkaConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topics: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, duration: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, callback: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can define our &lt;code&gt;createConsumer&lt;/code&gt; method quite simply as:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    KafkaConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(properties)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can define our &lt;code&gt;consume&lt;/code&gt; method such that it takes in the &lt;code&gt;properties&lt;/code&gt; and &lt;code&gt;serializer&lt;/code&gt; as with the producer, but will also take som &lt;code&gt;patterns&lt;/code&gt; to be used for subscribing to and the &lt;code&gt;duration&lt;/code&gt; above, and finally the callback &lt;code&gt;Consume&lt;/code&gt; function:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   patterns: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   duration: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   callback: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;   createConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;use&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { consumer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      consumer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;subscribe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(patterns)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; poll &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;         val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; records &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; consumer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;poll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Duration.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;ofMillis&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(duration))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;         val&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; records.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toList&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;               .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ConsumerRecord&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;String, String&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;               .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(serializer::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;deserialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;         return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      runBlocking&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;         callback&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(poll)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;consume&lt;/code&gt; function is very similar to the &lt;code&gt;produce&lt;/code&gt; function we defined previously, however now instead of being provided a function to send data we now have a function that will return that data&lt;/p&gt;
&lt;p&gt;Lastly, we can finish off the definition of our &lt;code&gt;Consumer&lt;/code&gt; using what we have above:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Consumer.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Consumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Config&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;IConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createConsumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topics: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, duration: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, callback: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties, serializer, topics, duration, callback)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h4&gt;Using the Consumer&lt;/h4&gt;
&lt;p&gt;Using the &lt;code&gt;Consumer&lt;/code&gt; follows a very similar pattern to the producer, however we need to create a loop that will poll for data and handle as necessary when data is received:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;App.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;@Serializable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ConsumerData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; message: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; key: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Int&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; instantiateAndConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Unit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;   val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; serializer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ConsumerData::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;   val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; consumer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Consumer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties, serializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;   runBlocking&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;       consumer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;consume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;listOf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;my-topic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;), &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) { poll &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;         while&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; messages &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; poll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;            println&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Received ${messages.size} messages&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            messages.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;               println&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Received: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;$message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;         }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above, we use a &lt;code&gt;while(true)&lt;/code&gt; loop to re-poll continuously but this can freely change on the implementation, similar to with the producer code&lt;/p&gt;
&lt;h3&gt;Stream Processing&lt;/h3&gt;
&lt;p&gt;In Kafka, we can think of a stream process as a combination of a consumer and producer such that data comes in from a topic and is sent to a different topic&lt;/p&gt;
&lt;p&gt;The thing that makes streams interesting is the builder API that the Kafka Java Library provides to us for defining the operations to be done on the stream data. For our implementation we&amp;#39;ll be referring to this as a &lt;code&gt;TransformProcessor&lt;/code&gt;, this processor needs to take in some data of type &lt;code&gt;TConsume&lt;/code&gt; and return data of type &lt;code&gt;TProduce&lt;/code&gt;, however, since we want to provide users complete flexibility in working with this data, we will instead more generally allow a user to convert a stream between the predefined data types, using the underlying library this is called a &lt;code&gt;KStream&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;From a type perspective, we can define a &lt;code&gt;TransformProcessor&lt;/code&gt; as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SerializedStream.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformProcessor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (stream: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; KStream&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;String, TProduce&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, we&amp;#39;re going to be starting this implementation from what we want, assuming that it is possible for us to in some way define a &lt;code&gt;KStream&lt;/code&gt; that is instantiated to work with our connection and the respective &lt;code&gt;TConsume&lt;/code&gt; and &lt;code&gt;TProduce&lt;/code&gt; data.&lt;/p&gt;
&lt;p&gt;We will also be using a type called &lt;code&gt;Produced&lt;/code&gt; which is what the Kafka Client uses to represent the data that the stream will return since this is what we need in order to send data to a processor&lt;/p&gt;
&lt;p&gt;Our implementation will be called a &lt;code&gt;SerializedStream&lt;/code&gt; and this looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SerializedStream.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.CoroutineScope&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.Dispatchers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.Job&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; kotlinx.coroutines.launch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.KafkaStreams&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.StreamsBuilder&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.kstream.KStream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.kstream.Produced&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformProcessor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (stream: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; KStream&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;String, TProduce&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Close&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Unit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typealias&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Process&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; suspend&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (close: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Close&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Unit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; builder: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;StreamsBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; producer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Produced&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; stream: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;   fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; startStreaming&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      processor: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      process: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   ): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Job&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      processor.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;to&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic, producer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; streams &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; KafkaStreams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;         builder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;build&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;         properties&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; scope &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; CoroutineScope&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Dispatchers.IO)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; scope.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;launch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;         streams.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;start&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;         process&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;         streams.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;close&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;   fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProcessor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;       processor: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TransformProcessor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;   ): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; processor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(stream)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above implementation we have an input to our &lt;code&gt;startStreaming&lt;/code&gt; function called &lt;code&gt;process&lt;/code&gt;, the &lt;code&gt;process&lt;/code&gt; function is a callback that needs to call &lt;code&gt;close&lt;/code&gt; once it is done running. When the &lt;code&gt;process&lt;/code&gt; function returns the processing will stop, the scope of this function also defines lifecycle of the stream processor and is used for that purpose&lt;/p&gt;
&lt;p&gt;So we have defined the processing methodology using a &lt;code&gt;KStream&lt;/code&gt; but have not provided a way to create a &lt;code&gt;KStream&lt;/code&gt;. Since the stream can be defined in many different ways, we can define this using a builder class called &lt;code&gt;StreamBuilder&lt;/code&gt;. This class will be instantiated with the Kafka connection properties and input/output serializers, thereafter it can produce methods for instantiating the &lt;code&gt;SerializedStream&lt;/code&gt; instance that we can use for data processing&lt;/p&gt;
&lt;p&gt;For the sake of our example we will provide a method called &lt;code&gt;fromTopic&lt;/code&gt; which returns a &lt;code&gt;SerializedStream&lt;/code&gt; that is configured to work on a single topic, and a &lt;code&gt;fromTopics&lt;/code&gt; method which will return a &lt;code&gt;SerializedStream&lt;/code&gt; that listens to multiple topics:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;StreamBuilder.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; za.co.nabeelvalley.kafka&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.common.serialization.Serdes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.StreamsBuilder&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.kstream.Consumed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; org.apache.kafka.streams.kstream.Produced&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; java.util.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; IStreamBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fromTopic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fromTopics&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topics: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;An implementation of this interface is as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;StreamBuilder.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StreamBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    consumeSerializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    producerSerializer: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ISerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) : &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Config&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;IStreamBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; inputSerde &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(consumeSerializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; consumed &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Consumed.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Serdes.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(), inputSerde)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; outputSerde &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Serializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(producerSerializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; produced &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Produced.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Serdes.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(), outputSerde)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fromTopic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; builder &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; StreamsBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; stream &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; builder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;mutableListOf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topic), consumed)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties, builder, produced, stream)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    override&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; fromTopics&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topics: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TConsume&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TProduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; builder &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; StreamsBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; stream &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; builder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(topics.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toMutableList&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(), consumed)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; SerializedStream&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties, builder, produced, stream)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above class makes use of the &lt;code&gt;produced&lt;/code&gt; and &lt;code&gt;consumed&lt;/code&gt; properties which are what Kafka will use for serializing and deserializing data in the stream&lt;/p&gt;
&lt;p&gt;And that&amp;#39;s about it as far as our implementation for streaming goes&lt;/p&gt;
&lt;h4&gt;Using the Stream Processor&lt;/h4&gt;
&lt;p&gt;We can use the stream processor code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;App.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fun&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; initializeAndProcess&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Properties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;): &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Job&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; producedSerializer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ProducerData::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; consumedSerializer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; JsonSerializer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ConsumerData::&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; streamBuilder &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; StreamBuilder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(properties, consumedSerializer, producedSerializer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; stream &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; streamBuilder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;fromTopic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;input-topic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; processor &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; stream.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getProcessor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { kStream &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        kStream.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;mapValues&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { key, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;            ProducerData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Message processed: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;$key&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; scope &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; CoroutineScope&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Dispatchers.IO)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; scope.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;launch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        stream.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;startStreaming&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;output-topic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, processor) { close &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;            coroutineScope&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;                println&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Processor starting&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;                // Non-blocking loop as long as the coroutine is active&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;                while&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (isActive) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;                    delay&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10_000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;                // close when no longer active&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;                close&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;                println&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Processor closed&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Most of this is just the normal construction that you will have for any instance of the stream client, what is interesting is the part where we define the processor:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;App.kt&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;kotlin&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; processor &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; stream.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getProcessor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { kStream &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    kStream.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;mapValues&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { key, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        ProducerData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Message processed: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;$key&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above example we are simply mapping a single record using &lt;code&gt;mapValues&lt;/code&gt;, this is very similar to the Collection methods available in Kotlin but is instead used to define how data will be transformed in the stream&lt;/p&gt;
&lt;p&gt;The processor we define is what will be executed on records or groups of records depending on how we want to handle the resulting data&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post we&amp;#39;ve covered the basic implementation of how we can interact with Kafka using the Kotlin programming language and built a small library that takes us through the basic use cases of Serializing, Producing, Consuming, and Processing stream data&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://kafka.apache.org/intro&quot; &gt;Introduction to Kafka&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.confluent.io/kafka-clients/java/current/overview.html&quot; &gt;Java Kafka Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Nvim Error when using Plugins</title><link>https://nabeelvalley.co.za/blog/2023/13-06/vim-errror-when-using-plugins.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/13-06/vim-errror-when-using-plugins.html</guid><description>Fix NVim Error Executing Lua with Plugins</description><pubDate>Tue, 13 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Nvim Error when using Plugins&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When trying to use an NVim plugin you may run into the following error message:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Error executing lua ...path/to/some/vim/file.lua&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This can happen due to a plugin update that was run or another plugin being installed that caused the working tree of the plugin to be out of date or in an invalid state&lt;/p&gt;
&lt;p&gt;To fix this, you may want to try updating and cleaning your plugins. In my case, I am using &lt;code&gt;VimPlug&lt;/code&gt; so the commands are:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;:PlugUpdate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;:PlugClean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Thereafter, quitting and reopening vim seems to usually fix the issue, if not then you may need to investigate the plugin itself&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>JPA Queries without the Magic</title><link>https://nabeelvalley.co.za/blog/2023/20-10/jpa-query-specifications.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/20-10/jpa-query-specifications.html</guid><description>Defining custom queries for JPA using specifications</description><pubDate>Fri, 20 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;JPA Queries without the Magic&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;If you&amp;#39;re just looking for the solution you can just &lt;a href=&quot;#the-solutions&quot; &gt;skip ahead&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The go-to way to build web applications with Java or Kotlin is using &lt;a href=&quot;https://spring.io/&quot; &gt;Spring&lt;/a&gt;. Spring is a pretty decent web framework that provides a lot of utilities for handling common web application related tasks&lt;/p&gt;
&lt;p&gt;However I find that Spring does a fair amount of compiler magic to make it work the way it does - of particular concern to this post is how Spring generates implementations for database queries using &lt;a href=&quot;https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#appendix.query.method.subject&quot; &gt;Query kewords&lt;/a&gt; as part of your function names which spring will resolve to a query on the underlying database&lt;/p&gt;
&lt;p&gt;Below is a short example of how we would use Spring to query our database to illustrate the problem:&lt;/p&gt;
&lt;h2&gt;The Example&lt;/h2&gt;
&lt;p&gt;Let us consider an application in which we have some entity in our system that we would like to store in a database and be able to search over&lt;/p&gt;
&lt;p&gt;In order to do this, we need to define a couple of things things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An Entity which represents that data structure for our User&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In Spring we can define entities, like a &lt;code&gt;User&lt;/code&gt; as a class with some annotations&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jakarta.persistence.Column;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jakarta.persistence.Entity;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jakarta.persistence.GeneratedValue;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jakarta.persistence.GenerationType;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jakarta.persistence.Id;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; jakarta.persistence.Table;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Entity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;User&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;GeneratedValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;strategy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; GenerationType.AUTO)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; id;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Column&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;unique&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; email;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol start=&quot;2&quot; &gt;
&lt;li&gt;A Repository which is the class through which we will interact with the database for the specific entity&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; org.springframework.data.jpa.repository.JpaRepository;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; org.springframework.stereotype.Repository;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; java.util.Optional;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For the repository all we really need is to use the &lt;code&gt;@Repository&lt;/code&gt; annotation which will register the repository with the Spring dependency injection, and we need to extend &lt;code&gt;JpaRepository&lt;/code&gt; which provides some base methods for our repository such as &lt;code&gt;findAll&lt;/code&gt;, &lt;code&gt;save&lt;/code&gt;, or &lt;code&gt;delete&lt;/code&gt; among others&lt;/p&gt;
&lt;p&gt;Up until this point, we haven&amp;#39;t seen anything too weird and the code thus far is fairly easy to reason about - however, this becomes interesting when we want to add a method like &lt;code&gt;findByEmail&lt;/code&gt; which we define in the interface as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    List&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findByEmail&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(String &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;email&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;That&amp;#39;s it, we don&amp;#39;t implement this anywhere - Spring will generate this implementation for us - weird - but okay. We can use this function anywhere we have a repsitory instance and it will behave as expected&lt;/p&gt;
&lt;h2&gt;Growing Pains&lt;/h2&gt;
&lt;p&gt;But now, what if we want the &lt;code&gt;findByEmail&lt;/code&gt; function to be case incensitive? Well seemingly we can just name this however so let&amp;#39;s try:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    List&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findByEmailCaseInsensitive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(String &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;email&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can try using that, but it won&amp;#39;t work - turns out the magic is documented at least, and Spring tells us that we actually need to use &lt;code&gt;IgnoreCase&lt;/code&gt; in the name - this makes use of the Query Keywords I mentioned above&lt;/p&gt;
&lt;p&gt;So sure, we can change this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    List&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findByEmailIgnoreCase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(String &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;email&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And also go and change everwhere we&amp;#39;re using that method, since it&amp;#39;s name now dictates its implementation we will need to keep in mind that if we ever want to change the implementation we will need to update all our clients&lt;/p&gt;
&lt;p&gt;But wait - that&amp;#39;s very UN-Java like isn&amp;#39;t it? This seems to break the entire purpose of using functions - if my function&amp;#39;s behaviour is directly dependant on it&amp;#39;s name then how is this any different to just repeating the implementation everywhere need this? We&amp;#39;re typing the same code either way&lt;/p&gt;
&lt;p&gt;Now, I&amp;#39;m not all complaints - using a half competent IDE we should be able to do this refactor fairly painlessly and move on with our day - this isn&amp;#39;t the main issue yet&lt;/p&gt;
&lt;p&gt;Where we start running into problems is when our queries need to get more complex, for example when we decide that we want the search to extend to something like a secondary email filed, for example if we add a new field to our entity, like &lt;code&gt;companyEmail&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Entity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Table&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;User&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // ... existing code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // new field&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Column&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; companyEmail;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;The Limit Does Exist&lt;/h2&gt;
&lt;p&gt;And we now need to update our email function to:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    List&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findByEmailIgnoreCaseOrCompanyEmailIgnoreCase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(String &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;email&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;That&amp;#39;s a bit rough right? There&amp;#39;s really no reason our method name should be that long - oh, and it won&amp;#39;t work either - even though this follows the JPA naming convention it&amp;#39;s just a little too complicated for the code generator to get right &lt;/p&gt;
&lt;p&gt;Okay, so now we&amp;#39;re stuck right? No - Why would I go on this rant if I don&amp;#39;t have a solution in my head&lt;/p&gt;
&lt;p&gt;Well, time to share it I guess&lt;/p&gt;
&lt;h2&gt;The Solution(s)&lt;/h2&gt;
&lt;h3&gt;Query Annotations&lt;/h3&gt;
&lt;p&gt;Spring gives us two escape hatches for handling the problem we just ran into - we can use the &lt;code&gt;@Query&lt;/code&gt; annotation which allows us to define a custom &lt;code&gt;JQL&lt;/code&gt; query (Not SQL) that is defined inline and will do the appropriate value substitutions as needed:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Query&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;SELECT u FROM User u WHERE LOWER(u.email) LIKE LOWER(:query) OR LOWER(u.comanyEmail) LIKE LOWER(:query)&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    List&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findByEmail&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(String &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;email&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, if this were the only option, I could live with it, it takes away some of the magic and gives me a decent amount of control over what I&amp;#39;m doing&lt;/p&gt;
&lt;p&gt;... but ... how can i say ... It&amp;#39;s ugly&lt;/p&gt;
&lt;p&gt;Even if we assume that we don&amp;#39;t somehow have any errors in the above string, it&amp;#39;s just a little odd - like other ORMs have lovely fluent interfaces like &lt;code&gt;LINQ&lt;/code&gt; in C# or &lt;code&gt;knex&lt;/code&gt; or &lt;code&gt;prisma&lt;/code&gt; in Javascript/TypeScript that understand SQL and fit naturally into our programming languge&lt;/p&gt;
&lt;h3&gt;Specifications&lt;/h3&gt;
&lt;p&gt;Specifications provide us with a way to define our query within our programming language, and I think that&amp;#39;s nice, so here&amp;#39;s how they work&lt;/p&gt;
&lt;p&gt;In order to use specificiations we need to do a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define the specification method&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It doesn&amp;#39;t matter too much where we define the specification, but for our example we&amp;#39;ll put it in a static class so we can use it wherever:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; org.springframework.data.jpa.domain.Specification;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserSpecification&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     * Search for an User using a free text search on the email and name fields&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; search&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; text to be searched&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@return&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; a specification that can be used with the `repository.findAll()` on a `JpaSpecificationExecutor`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; static&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Specification&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;searchForUserByEmail&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(String &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;search&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; likeSearch&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; search.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toLowerCase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (root, query, criteriaBuilder) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;            return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; criteriaBuilder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;or&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                    criteriaBuilder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;like&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(criteriaBuilder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;lower&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(root.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)), likeSearch),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;                    criteriaBuilder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;like&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(criteriaBuilder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;lower&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(root.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;companyEmail&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)), likeSearch)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The structure of the specification is a little verbose but you could refactor this to be a bit more reusable if you wanted&lt;/p&gt;
&lt;ol start=&quot;2&quot; &gt;
&lt;li&gt;Extend the &lt;code&gt;JpaSpeficationExecutor&lt;/code&gt; on our repository&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can delete all the methods in the repository and add the &lt;code&gt;JpaSpecificationExecutor&amp;lt;User&amp;gt;&lt;/code&gt; to the list of things we&amp;#39;re extending&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ... existing imports&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; org.springframework.data.jpa.repository.JpaSpecificationExecutor;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; UserRepository&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JpaRepository&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;Long&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JpaSpecificationExecutor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; { }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above definition will provide us with two nice method on the repository, namely &lt;code&gt;findAll&lt;/code&gt; and &lt;code&gt;findOne&lt;/code&gt; which both take a &lt;code&gt;Speficication&lt;/code&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot; &gt;
&lt;li&gt;Use the speficication with our repository&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now that we have everything defined, we can use this in some part of our application as such:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;java&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; spec&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; UserSpecification.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;searchForUserByEmail&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob@email.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; userRepository.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findOne&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(spec);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// or for findAll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; results&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; userRepository.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;findAll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(spec)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And that&amp;#39;s it, In my opinion the &lt;code&gt;Specification&lt;/code&gt; solution is a bit easier to manage within the context of the greater codebase without having to worry about too much compile time magic and possible typos in the &lt;code&gt;JQL&lt;/code&gt; query&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I think either of the the provided solutions are fair and give us with a good way to manage more complex queries more flexibly in a way that isolates our implementation from where we intend to use the code&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh, and since you made it this far - I&amp;#39;m SO sorry you&amp;#39;re writing Java and I wish your sanity all the best&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Postman Flows</title><link>https://nabeelvalley.co.za/blog/2023/23-03/postman-flows.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/23-03/postman-flows.html</guid><description>First impressions playing with the new Postman Flows</description><pubDate>Thu, 23 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Postman Flows&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Postman is a tool used for making HTTP requests during development that enables easy testing and experimentation with HTTP/REST APIs&lt;/p&gt;
&lt;p&gt;Recently Postman released something called Flows which is a visual editor for building API flows between different applications and stitching them together into some kind of output view&lt;/p&gt;
&lt;p&gt;Flows can be done to DO things but can also be used to SHOW information based on the data that passes through them&lt;/p&gt;
&lt;p&gt;Below is an example of a Postman Flow that reads the posts from my website and lists/counts them when run from postman&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;2.1160058737151246&quot; orientation=&quot;horizontal&quot; alt=&quot;postman-flow-example&quot; src=&quot;/optimized-images/public/content/blog/2023/23-03/postman-flow-example.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Another example of a Postman Flow is of their &lt;a href=&quot;https://www.postman.com/postman/workspace/utility-flows/flow/64123b57c224290033fcb089&quot; &gt;Stock dashboard example&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;For more information on how to build an use a flow you can take a look at the &lt;a href=&quot;https://learning.postman.com/docs/postman-flows/gs/flows-overview/&quot; &gt;Postman Flows Overview&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Postman flows seems targeted at more technical users. In addition to this I think &lt;a href=&quot;http://ifttt.com/&quot; &gt;IFTTT&lt;/a&gt; is worth taking a look at if you&amp;#39;re interested in doing some small flow-style automations&lt;/p&gt;
&lt;p&gt;For a bit of a more self-hosted alernative, you can also take a look at &lt;a href=&quot;https://nodered.org&quot; &gt;Node-RED&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Let&#39;s talk about Feeds</title><link>https://nabeelvalley.co.za/blog/2023/24-01/about-rss.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/24-01/about-rss.html</guid><description>A short introduction to RSS feeds</description><pubDate>Tue, 24 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Let&amp;#39;s talk about Feeds&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Order Up&lt;/h2&gt;
&lt;p&gt;Life&amp;#39;s busy and disastrous and trying to pop in and talk to myself for a few hours is unattainable most of the time&lt;/p&gt;
&lt;p&gt;Recently I&amp;#39;ve gotten really into RSS. RSS is short for &lt;code&gt;Really Simple Syndication&lt;/code&gt; and it&amp;#39;s basically just a format/standard that enables websites to share their content in a way that&amp;#39;s easy for other websites or applications to consume&lt;/p&gt;
&lt;h2&gt;Starter&lt;/h2&gt;
&lt;p&gt;An RSS Feed is really just an XML file that contains information on a website&amp;#39;s content, and depending on the nature of the website this is usually something like a blog or podcast feed, but I&amp;#39;ve also seen RSS used for things like project statuses or website uptime information&lt;/p&gt;
&lt;h2&gt;Main Course&lt;/h2&gt;
&lt;p&gt;Here&amp;#39;s a sample RSS Feed that I found on &lt;a href=&quot;http://www.rss-tools.com/rss-example.htm&quot; &gt;RSS Tools&lt;/a&gt; that I modified a bit to represent something you might see when working with websites or blog content:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;xml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;?&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;xml&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; version&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; encoding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;rss&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; version&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;channel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;RSS Example&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is an example of an RSS feed&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;http://www.domain.com/link.htm&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;lastBuildDate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Mon, 28 Aug 2006 11:12:55 -0400&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;lastBuildDate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;pubDate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Tue, 29 Aug 2006 09:00:00 -0400&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;pubDate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item Example&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is an example of an Item&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;description&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;http://www.domain.com/link.htm&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;link&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;guid&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isPermaLink&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;1102345&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;guid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;pubDate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Tue, 29 Aug 2006 09:00:00 -0400&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;pubDate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;content:encoded&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;This is some content&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;content:encoded&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;item&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;channel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;rss&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above example we can see a &lt;code&gt;channel&lt;/code&gt; which defines a source for content&lt;/p&gt;
&lt;p&gt;Next up we&amp;#39;ve got the &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;link&lt;/code&gt;, &lt;code&gt;lastBuildDate&lt;/code&gt;, and &lt;code&gt;pubDate&lt;/code&gt; which are the metadata for the overall feed and are required for readers that may be accessing the feed&lt;/p&gt;
&lt;p&gt;Now, all of that is really cool, but we&amp;#39;re not into the juicy bits yet - diving into the content itself we see in the &lt;code&gt;item&lt;/code&gt; section.&lt;/p&gt;
&lt;p&gt;A feed can define multiple &lt;code&gt;item&lt;/code&gt; tags - each of these would have some metadata as well as the actual content associated with the post&lt;/p&gt;
&lt;p&gt;In the example, each &lt;code&gt;item&lt;/code&gt; has the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;description&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;link&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;guid&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;content:encoded&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above fields are pretty so-so, but the part I find intriguing is the &lt;code&gt;guid&lt;/code&gt; which is any unique identifier for an item in a feed, this doesn&amp;#39;t have a specific format but just needs to be unique to the feed.&lt;/p&gt;
&lt;p&gt;Next, is the &lt;code&gt;content:encoded&lt;/code&gt; section which is what the feed uses to share it&amp;#39;s content - this can either be plain text or HTML, and it&amp;#39;s up to the client to figure it out - based on this I suppose you could really share any content or data which is a pretty cool concept&lt;/p&gt;
&lt;h2&gt;Dessert&lt;/h2&gt;
&lt;p&gt;Overall, RSS is pretty simple as a format and has some issues and limitation - versions prior to RSS 2.0 can also be a bit difficult to work with as it&amp;#39;s not totally standardised&lt;/p&gt;
&lt;p&gt;Another issue I&amp;#39;ve encountered when working with RSS is the size of the file itself. Some feeds post frequently and may have very long posts. This can lead to very long posts&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve noticed that some blogs with large RSS feeds choose to only store their latest items on the RSS feed, this means that consumer interested in reading older items need to have some cache of their own which was made when the items were initially posted - you could use the &lt;code&gt;guid&lt;/code&gt; for this or some kind of diffing method but pretty much anything outside of the XML file delivered is the job of a consumer to work with&lt;/p&gt;
&lt;h2&gt;The Bill&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve seen a lot of revived interest in the RSS format but there are also competitors to the format like ATOM which is a more complete standard and supports features like paged feeds and explicit content type definitions&lt;/p&gt;
&lt;p&gt;ATOM seems to solve the few issues I have with RSS but RSS is still &lt;strong&gt;literally everywhere&lt;/strong&gt; which is tough to fight&lt;/p&gt;
&lt;p&gt;My latest side project is an RSS reader called &lt;a href=&quot;https://articly.vercel.app&quot; &gt;Articly&lt;/a&gt; which is built with Svelte/SvelteKit since I really wanted to get a feeling for the framework to build a full application and this seemed like a fun opportunity to do that&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Structuring HTML Content</title><link>https://nabeelvalley.co.za/blog/2023/26-01/html-to-structured-content.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/26-01/html-to-structured-content.html</guid><description>Transforming HTML into structured data to work with EditorJS</description><pubDate>Thu, 26 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Structuring HTML Content&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Isn&amp;#39;t HTML a structure?&lt;/h2&gt;
&lt;p&gt;HTML content is structured as a tree - while this is useful for the medium, this structure isn&amp;#39;t very convenient for transforming into data that can be used outside of the web or with libraries that use content in a more flat structure&lt;/p&gt;
&lt;p&gt;While building &lt;a href=&quot;https://articly.vercel.app&quot; &gt;Articly&lt;/a&gt; I wanted to use a library called &lt;a href=&quot;https://editorjs.io&quot; &gt;EditorJS&lt;/a&gt; for displaying and making text content interactive. An immediate problem I ran into was importing content into the editor since it requires the data in a specific format - which is not HTML but rather an array of objects with simplified content&lt;/p&gt;
&lt;h2&gt;StackOverflow is helpful sometimes&lt;/h2&gt;
&lt;p&gt;In order to get the content into the EditorJS format, I needed to find a way to transform the HTML that I had from scraping the web and reading RSS feeds into something I could use as some kind of base&lt;/p&gt;
&lt;p&gt;After a little bit of searching, I found this handy function on &lt;a href=&quot;https://stackoverflow.com/questions/12980648/map-html-to-json&quot; &gt;StackOverflow&lt;/a&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//Recursively loop through DOM elements and assign properties to object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; treeHTML&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;element&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;object&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;type&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; element.nodeName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nodeList &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; element.childNodes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (nodeList &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (nodeList.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nodeList.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (nodeList[i].nodeType &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(nodeList[i].nodeValue)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;else&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;          treeHTML&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(nodeList[i], object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;][object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (element.attributes &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (element.attributes.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;attributes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; element.attributes.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; i&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        object[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;attributes&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;][element.attributes[i].nodeName] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          element.attributes[i].nodeValue&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using the above as a guideline, I concluded that the main thing that I need was to iterate over the HTML content in a way that would allow me to build a content array which is recursive - the idea at this point is not to remove the tree structure, but rather to transform it into something that&amp;#39;s a bit easier to work with&lt;/p&gt;
&lt;h2&gt;A different tree&lt;/h2&gt;
&lt;p&gt;Now that I had an idea of how to approach the problem, the next step was to define the structure I wanted, below is the final structure I decided on:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The source HTML element object needs to be stored as this may useful to downstream processors&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;tagName&lt;/code&gt; of the element will be needed to determine how a specific element needs to be handled&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;textContent&lt;/code&gt; and &lt;code&gt;innerHTML&lt;/code&gt; of the element to be stored - this is the core data of the element&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;attributes&lt;/code&gt; of the HTML element should be unwrapped to make it easier for downstream code to read&lt;/li&gt;
&lt;li&gt;The children of the element need to be converted into the the same type by recursively following steps 1-5&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on the above, the type definition can be seen below along with the implementation:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TagName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Uppercase&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HTMLElementTagNameMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HTMLStringContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  element&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Element&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  tagName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TagName&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  textContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  htmlContent&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HTMLStringContent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  attrs&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  children&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; transform&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;el&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Element&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  element: el,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // tag names are strings internally but that&amp;#39;s not very informative downstream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  tagName: el.tagName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TagName&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  textContent: el.textContent &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  htmlContent: el.innerHTML,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  children: Array.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(el.children).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(transform),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  attrs: Array.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(el.attributes).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;reduce&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;acc&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;acc, [name]: value }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now that I have the data as a tree structure, we can pass in some simple HTML to see what pops out the other end.&lt;/p&gt;
&lt;p&gt;Given the following HTML content:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello World&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can transform it like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// use the DOM to parse it from a string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; el&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; DOMParser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parseFromString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(html, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;text/html&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// the convertHtmlToBlocks function takes an HTML ELement&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; transformed&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(el)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;transformed&lt;/code&gt; data looks something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;element&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;tagName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;BODY&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;textContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  Hello World&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n\n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  \n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    \n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  \n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;htmlContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;lt;p&amp;gt;Hello World&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;lt;section&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;lt;img src=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;hello.jpg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; alt=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;this is an image&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;lt;/section&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;/div&amp;gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;children&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;element&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;tagName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;DIV&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;textContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  Hello World&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n\n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  \n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    \n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  \n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;htmlContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;lt;p&amp;gt;Hello World&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;lt;section&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;lt;img src=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;hello.jpg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; alt=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;this is an image&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;lt;/section&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;children&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;element&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;tagName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;P&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;textContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;htmlContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;children&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;attrs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;element&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;tagName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;SECTION&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;textContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    \n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;htmlContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;lt;img src=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;hello.jpg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; alt=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;this is an image&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;children&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;              &amp;quot;element&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;              &amp;quot;tagName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;IMG&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;              &amp;quot;htmlContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;              &amp;quot;children&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;              &amp;quot;attrs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: { &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;&amp;quot;alt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;          &amp;quot;attrs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;      &amp;quot;attrs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;attrs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Not too dissimilar to the structure raw HTML we would have had if we just used &lt;code&gt;DOMParser&lt;/code&gt; directly, however it now has a lot less noise&lt;/p&gt;
&lt;h2&gt;Deforestation&lt;/h2&gt;
&lt;p&gt;As I mentioned earlier, we need to transform the data into a flat array of items - so the question that comes up now is - how do we do that?&lt;/p&gt;
&lt;p&gt;Looking at the input HTML we used, we can break things up into two types of elements - containers and content&lt;/p&gt;
&lt;p&gt;Containers are pretty much useless to the content structure we&amp;#39;re trying to build - the content is all we really care about&lt;/p&gt;
&lt;p&gt;This is an important distinction because it tells us what we can throw away&lt;/p&gt;
&lt;p&gt;Secondly, we can think of the content inside of a container as an array of content, once we remove all the containers, this content will become flat&lt;/p&gt;
&lt;p&gt;So for example, this HTML:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello World&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;When we remove the containers can be thought of as:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello World&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which can be thought of as an array like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;[paragraph, image]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is our end goal. In order to get here we still have to figure out two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How can we separate out the containers from the content&lt;/li&gt;
&lt;li&gt;How can we transform the content into the structure that&amp;#39;s useful to us&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Separating the leaves from the wood&lt;/h2&gt;
&lt;p&gt;If we think as containers as having no meaningful data, and just being containers for content, then we can conclude that a way to view the data structure is as an array of content - the container is the array, and the content is the items in the array&lt;/p&gt;
&lt;p&gt;So, we can write a transformer for a container as something that just returns an array of content&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.children&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above is pretty useful, since this means that the following HTML:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello World&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Will be essentially be converted to this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello World&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, we still see that there&amp;#39;s a &lt;code&gt;section&lt;/code&gt; leftover since we only returned one layer of children. Since we already have a way to get rid of the wrapper, we can just apply that to the child that&amp;#39;s a section,&lt;/p&gt;
&lt;p&gt;So we could have something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    isContainer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; child&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now the function is a bit weird because the inner map is either returning an array if the &lt;code&gt;child&lt;/code&gt; is a container, or a single &lt;code&gt;child&lt;/code&gt; if it&amp;#39;s not - for consistency, let&amp;#39;s just always return an array:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    isContainer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [child]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Much better, but now we&amp;#39;ve introduced something weird - instead of just returning a &lt;code&gt;TransformResult[]&lt;/code&gt; we&amp;#39;re now returning a &lt;code&gt;TransformResult[][]&lt;/code&gt; - let&amp;#39;s just leave this here for now, we can always unwrap the arrays later - importantly we now know that we&amp;#39;ve eliminated the wrappers, so the content we&amp;#39;re left with now represents:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello World&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello.jpg&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; alt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;this is an image&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So this is pretty great, and is the general idea of how we can unwrap things - next up we can talk about transforming the specific elements into useful data blocks&lt;/p&gt;
&lt;h2&gt;Building blocks&lt;/h2&gt;
&lt;p&gt;EditorJS has different sections - blocks as it calls them - of content. These are simple Javascript objects that represent the data for the block&lt;/p&gt;
&lt;p&gt;For the sake of our discussion, we&amp;#39;re going to consider two blocks - &lt;code&gt;ParagraphBlock&lt;/code&gt; and &lt;code&gt;ImageBlock&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The simplified types that represent their data can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ParagraphBlock&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;paragraph&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    text&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SimpleImageBlock&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;image&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    caption&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can look at the the &lt;code&gt;TransformResult&lt;/code&gt; for each of the above elements from when we passed the HTML into our &lt;code&gt;transform&lt;/code&gt; function previously, we can see&lt;/p&gt;
&lt;p&gt;For the paragraph:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;element&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;tagName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;P&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;textContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;htmlContent&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;children&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;attrs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which can be translated to the &lt;code&gt;ParagraphBlock&lt;/code&gt; data as:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;paragraph&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    text&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;A function for doing this could look something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertParagraph&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ParagraphBlock&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.textContent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;paragraph&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        data: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          text: data.textContent,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Cool, this lets us transform a paragraph into some structured data.&lt;/p&gt;
&lt;p&gt;We can do something similar for images:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertImage&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ImageBlock&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.attrs.src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;image&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        data: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          url: data.attrs.src,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          caption: data.attrs.alt &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;So now that we know how to transform the HTML into something useful, remove the wrappers, and represent individual HTML sections as content blocks, we can put it all together into something that lets us convert a section of HTML fully:&lt;/p&gt;
&lt;p&gt;First, we can update the &lt;code&gt;removeContainer&lt;/code&gt; function to call the converter on the type of tag that it finds:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// note that we need a handler for BODY since the `DOMParser` will always add a body element when parsing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isContainer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.tagName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;BODY&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ||&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.tagName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;DIV&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ||&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.tagName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;SECTION&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isContainer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;else&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (child.tagName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;IMG&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; block&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertImage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; block &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [block] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;else&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (child.tagName &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;P&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; block&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertParagraph&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; block &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [block] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, you can probably see a pattern that&amp;#39;s going to arise as we add more and more elements that we want to handle - so it may be better to create a list of handlers for different tag types:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Block&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ParagraphBlock&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ImageBlock&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; handlers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TagName&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Block&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&amp;gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // content blocks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  IMG: convertImage,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  P: convertParagraph,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // container blocks - we will always want to remove these&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  DIV: removeContainer,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  SECTION: removeContainer,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  BODY: removeContainer,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using the above structure, we can tweak the &lt;code&gt;convertImage&lt;/code&gt; and &lt;code&gt;convertParagraph&lt;/code&gt; functions a bit so that they return the &lt;code&gt;Block[]&lt;/code&gt; consistently:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertParagraph&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ParagraphBlock&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.textContent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;paragraph&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          data: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            text: data.textContent,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertImage&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ImageBlock&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  data.attrs.src&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;image&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          data: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            url: data.attrs.src,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            caption: data.attrs.alt &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can update the &lt;code&gt;removeContainer&lt;/code&gt; function to handle things a bit more genericallly:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; removeContainer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TransformResult&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Block&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; contentArr&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data.children.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; handlers[child.tagName]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;handler) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handler&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contentArr.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;flat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;If you&amp;#39;re really attentive, you&amp;#39;ll notice the &lt;code&gt;contentArr.flat(1)&lt;/code&gt; that was added in the above snippet, this flattens the &lt;code&gt;Block[][]&lt;/code&gt; into a &lt;code&gt;Block[]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Once we&amp;#39;ve got that, we can define a &lt;code&gt;convert&lt;/code&gt; function that will take the HTML and output the structured blocks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convert&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;el&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Element&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Block&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; transformed&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(el)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; initialHandler&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; handlers[transformed.tagName]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;initialHandler) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;No handler found for top-level wrapper&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; initialHandler&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(transformed)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Adding more content types&lt;/h2&gt;
&lt;p&gt;That&amp;#39;s about it, to handle more specific types of content or other HTML elements is just a matter of following the recipe that we did above:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Define if an element is a container or content&lt;/li&gt;
&lt;li&gt;If it&amp;#39;s a container, just use the &lt;code&gt;removeContainer&lt;/code&gt; handler&lt;/li&gt;
&lt;li&gt;If it&amp;#39;s content then define a handler for the specific kind of content&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you roll this out for loads of elements you&amp;#39;ll eventually have a pretty robust converter&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That&amp;#39;s it! We&amp;#39;ve covered the basics for building a transformer like this, and once you have a good feel for how this works, the concepts can be applied to loads of different usecases&lt;/p&gt;
&lt;p&gt;If you&amp;#39;d like to see the completed version of my converter, you can take a look at the &lt;a href=&quot;https://github.com/nabeelvalley/html-editorjs&quot; &gt;&lt;code&gt;html-editorjs&lt;/code&gt; GitHub repo&lt;/a&gt; and if you&amp;#39;d like to look at it in action in an application then take a look at &lt;a href=&quot;https://articly.vercel.app&quot; &gt;Articly&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Using Type Guards and Unions to prevent bugs and increase maintainability</title><link>https://nabeelvalley.co.za/blog/2023/26-06/type-guards-and-unions-typescript.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/26-06/type-guards-and-unions-typescript.html</guid><description>A practical introduction to type guards and union types</description><pubDate>Mon, 26 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Using Type Guards and Unions to prevent bugs and increase maintainability&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When working with a dynamic language, like Javascript, a problem that we can often run into is one where a variable may be of multiple possible types in a given place in our code. Due to this, we often run into a need to check the type of an object&lt;/p&gt;
&lt;h2&gt;The Scene&lt;/h2&gt;
&lt;p&gt;For the sake of introducing the need for type guards, we&amp;#39;re going to consider an imaginary news site in which users can read articles posted to the site. For our site, we want to enable users to add comments and interact with articles. For this purpose, we require that each user is logged in and exists in our database&lt;/p&gt;
&lt;p&gt;The object we use for representing a user who just reads our site is as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; reader&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  username: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;john&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  email: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;john@email.com&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;After some time, we decide to make it such that certain users can create articles on the website. To do this, we add a value on the user that states that the user is a writer:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; writer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  username: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;smith&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  email: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;smith@email.com&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  isWriter: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is great, our data now reflects that we have a user type that can post articles to the website.&lt;/p&gt;
&lt;p&gt;The site is growing well and the content available is flourishing, by we seem to be getting a frequent complaints from users that some articles are not appropriate for the site or may be incorrect or misleading&lt;/p&gt;
&lt;p&gt;So, to mitigate this issue, we decide that for our website we want to add a new type of permission that defines users that are responsible for moderating content. However, to prevent a conflict of interest - moderators are not allowed to write articles for the site&lt;/p&gt;
&lt;p&gt;So we choose to add a field for that indicates a user is a moderator:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; moderator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  username: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;bob&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  email: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;bob@email.com&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  isWriter: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  isModerator: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Based on this, we update the application types to account for the new field, and we have the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  username&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  isWriter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  isModerator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We update the application to handle the above solution. We even add a few helper methods in our code that allow us to determine if a user is a writer or moderator&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isWriter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.isWriter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isModerator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.isModerator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Fantastic! We&amp;#39;re happy with our implementation and we release the code into production&lt;/p&gt;
&lt;p&gt;Everything is going great, our moderators are keeping the content quality up and our writers are writing great content&lt;/p&gt;
&lt;h2&gt;The Bug&lt;/h2&gt;
&lt;p&gt;After a few weeks though, readers start to notice a problem - some articles that are taken down by moderators seem to be reappearing - it looks as if some malicious moderator is re-enabling bad articles&lt;/p&gt;
&lt;p&gt;Upon some further investigation, the team notices that all these articles are ones in which the moderator is the writer of the article - but this shouldn&amp;#39;t have happened right? We said that each moderator should not be able to also function as a writer&lt;/p&gt;
&lt;p&gt;Eventually, we track down the bug that made this possible, it was in the function called &lt;code&gt;convertUserToModerator&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertUserToModerator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  user.isModerator &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The issue was caused by us not setting the &lt;code&gt;isWriter&lt;/code&gt; field to &lt;code&gt;false&lt;/code&gt; in the above function, cool - so we just fix that:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; convertUserToModerator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  user.isModerator &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  user.isWriter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Great - we deploy the fix and migrate to ensure that &lt;code&gt;isWriter&lt;/code&gt; is set to &lt;code&gt;false&lt;/code&gt; for all existing moderators. The issue seems to be fixed, but after a while users start reporting that the problem is happening again&lt;/p&gt;
&lt;p&gt;The cause seems to be the same - it looks like users are somehow still having &lt;code&gt;isWriter&lt;/code&gt; and &lt;code&gt;isModerator&lt;/code&gt; simultaneously set to &lt;code&gt;true&lt;/code&gt; and ending up with a permission that shouldn&amp;#39;t be possible in our system&lt;/p&gt;
&lt;h2&gt;Impossible States&lt;/h2&gt;
&lt;p&gt;So we decide to investigate the problem and determine that the reason we are running into this bug seems to be due to some fundamental way that the data has been defined&lt;/p&gt;
&lt;p&gt;Since each user can have &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; for any combination of &lt;code&gt;isWriter&lt;/code&gt; and &lt;code&gt;isModerator&lt;/code&gt; we end up representing something unintended which can be seen in the table of possible combinations below:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Type&lt;/th&gt;
&lt;th&gt;&lt;code&gt;isWriter === true&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;isWriter === false&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isModerator === true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unknown&lt;/td&gt;
&lt;td&gt;Moderator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;isModerator === false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Writer&lt;/td&gt;
&lt;td&gt;Reader&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;From the above, we can see that we have a state that is not handled in the current code - this &amp;quot;Unknown&amp;quot; state. In this state, the &lt;code&gt;isModerator&lt;/code&gt; and &lt;code&gt;isWriter&lt;/code&gt; functions return &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We want this state to be impossible in our code. This is not a state that our application should ever have to consider. From a type-design perspective, it&amp;#39;s not enough to handle these impossible states, we need to prevent them from existing in the first place&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;The problem above stems from the fact that we&amp;#39;re using two different states to represent something that should be a single state. From the above diagram, we can resolve the following valid types of users in our system&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reader - reads and adds comments to articles&lt;/li&gt;
&lt;li&gt;Writer - writes articles&lt;/li&gt;
&lt;li&gt;Moderator - moderates articles, does not write articles&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using these user types, we can update the &lt;code&gt;User&lt;/code&gt; definition from above:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;reader&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;writer&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;moderator&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  username&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; field allows us to determine the type of a user. We can then use this value to check the type of a user and use this to inform how we use the object down the line&lt;/p&gt;
&lt;h2&gt;Extending the Moderator&lt;/h2&gt;
&lt;p&gt;Our solution is running well and we have managed to fully eliminate the bug.&lt;/p&gt;
&lt;p&gt;But now, the moderators are a little bored with their duties and would like some way that they can compete with each other on the quality of their content moderation - so they decide to create a leaderboard in which they look at how many articles they have read and approved or denied - as interest goes however, the moderators reach out to the development team and ask if it would be possible to add the number of approvals and denials so that the moderators don&amp;#39;t need to calculate this manually every month for their leaderboard&lt;/p&gt;
&lt;p&gt;The development team has the idea to add these scores into the &lt;code&gt;User&lt;/code&gt; definition type:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;reader&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;writer&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;moderator&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  username&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  approvedArticles&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  deniedArticles&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;During a PR review session, the team decides that this is a bit weird since it implies that any user can have some approved or denied articles - this doesn&amp;#39;t make sense, so someone suggests to use a &lt;strong&gt;Discriminated Union&lt;/strong&gt; in which only users of the &lt;code&gt;moderator&lt;/code&gt; type can have these properties - the developer also says that this will make it easier later to add additional fields to any role without having to worry about the implication of this on other roles&lt;/p&gt;
&lt;p&gt;The team decides that they want to have a &lt;code&gt;Base&lt;/code&gt; user which has some shared properties and a union which adds additional fields&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;BaseUser&lt;/code&gt; user has a generic parameter called &lt;code&gt;Type&lt;/code&gt; which is the &lt;code&gt;type&lt;/code&gt; for the user, since we want to ensure that each possible user type has this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BaseUser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  username&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  email&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Each specialized user type can inherit from &lt;code&gt;BaseUser&lt;/code&gt; with a specific type applied, for the &lt;code&gt;writer&lt;/code&gt; and &lt;code&gt;reader&lt;/code&gt; types, these can just be aliases to the base interface&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReaderUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BaseUser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;reader&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WriterUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BaseUser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;writer&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;moderator&lt;/code&gt; however, will need to extend this to add the additional properties:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ModeratorUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; BaseUser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;moderator&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  approvedArticles&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  deniedArticles&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Lastly, the three types above can be used to define a single type called &lt;code&gt;User&lt;/code&gt; which has the same functionality as the &lt;code&gt;User&lt;/code&gt; interface we&amp;#39;ve been using until now:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReaderUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WriterUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ModeratorUser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The code above is the Typescript syntax for defining a &lt;strong&gt;Union&lt;/strong&gt; which is a type that can be one of multiple types. Each type in the Union is separated by the &lt;code&gt;|&lt;/code&gt;. The union we have above is a special type of union called a &lt;strong&gt;Discriminated Union&lt;/strong&gt; which is a special type of Union that has a field called a &lt;strong&gt;discriminator&lt;/strong&gt; which uniquely identifies each element of the union - in our case this is the &lt;code&gt;type&lt;/code&gt; field of &lt;code&gt;BaseUser&lt;/code&gt; which used the generic &lt;code&gt;Type&lt;/code&gt; parameter&lt;/p&gt;
&lt;p&gt;In our backend code, we can now use the &lt;code&gt;type&lt;/code&gt; property of our user to conditionally fetch the data needed to populate the moderator object&lt;/p&gt;
&lt;h2&gt;Checks, Checks&lt;/h2&gt;
&lt;p&gt;As the codebase grows, the team writes some functions to check the type of the user so that specific computations can be done, for example checking the total number of articles a moderator has been reviewed. An example of one of these checks can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isModerator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.type &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;moderator&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above check is used in quite a few places, like when counting the total number of articles reviewed:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getTotalArticlesReviewed&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isModerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(user)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; moderatorUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ModeratorUser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; moderatorUser.approvedArticles &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; moderatorUser.deniedArticles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Similar casting patterns as above seem to be cropping up in a lot of places, another example is when listing the moderators that a user follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; moderatorUsers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; users.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;filter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(isModerator) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ModeratorUser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Type Guards&lt;/h2&gt;
&lt;p&gt;The above solutions use &lt;strong&gt;Type Assertions&lt;/strong&gt; which allow a user to override the Typescript Compiler&amp;#39;s type system to manually state the type of an object - this is dangerous because it essentially means that we give up type checking at that point in the code&lt;/p&gt;
&lt;p&gt;The type assertions around user types are leading to lots of bugs, the team has a discussion about how this problem can be solved and someone suggests using a &lt;strong&gt;Type Guard&lt;/strong&gt;. Type Guards are functions that can be used to check if a given variable meets a specific criterion under which it can be considered a narrower type that the input type. The difference between a Type Guard in this context and a regular function is that a Type Guard returns type information that can be used to inform the Typescript compiler about the state of a variable&lt;/p&gt;
&lt;p&gt;The proposed example is to convert the &lt;code&gt;isModerator&lt;/code&gt; function into an &lt;strong&gt;Assertion Function&lt;/strong&gt; by converting the return type from &lt;code&gt;boolean&lt;/code&gt; to &lt;code&gt;user is ModeratorUser&lt;/code&gt; - this assertion tells the compiler that within the scope that the check is &lt;code&gt;true&lt;/code&gt;, the value is of the stated type and not the original type&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;isModerator&lt;/code&gt; can be updated as such:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isModerator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ModeratorUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  user.type &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;moderator&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This means that when using the code above, we no longer need to cast since Typescript can infer the variable appropriately&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getTotalArticlesReviewed&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;user&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isModerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(user)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // within the scope of this condition the `user` type is known to be `ModeratorUser`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.approvedArticles &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; user.deniedArticles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// the `.filter` function accepts the type guard and can now infer that moderatorUsers is `ModeratorUser[]`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; moderatorUsers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; users.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;filter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(isModerator)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Discriminated Unions and type Guards are a powerful methods that can be used for working with complex object types and encoding application rules into your type system to minimize bugs and make code easier to extend&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;On this site the following posts contain content relative to this one:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2022/31-05/type-narrowing&quot; &gt;Type Narrowing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/docs/javascript/typescript-basics&quot; &gt;Typescript Basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Typescript documentation also mentions the above topics in a few different places:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions&quot; &gt;Assertion Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions&quot; &gt;Discriminated Unions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions&quot; &gt;Unions and Intersection Types&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the following series from &lt;a href=&quot;https://fsharpforfunandprofit.com/&quot; &gt;F# for Fun and Profit&lt;/a&gt; is something I often find myself coming back to on the topic of type design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fsharpforfunandprofit.com/posts/designing-with-types-intro/&quot; &gt;Designing with types: Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/&quot; &gt;Designing with types: Making illegal states unrepresentable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Update or Append to DynamoDB Attributes</title><link>https://nabeelvalley.co.za/blog/2023/28-02/dynamo-db-update-attribute.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/28-02/dynamo-db-update-attribute.html</guid><description>Use UpdateExpressions to modify DynamoDB items without reading them from the database</description><pubDate>Tue, 28 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Update or Append to DynamoDB Attributes&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;DynamoDB Overview&lt;/h2&gt;
&lt;p&gt;DynamoDB is AWS&amp;#39;s No SQL Database Service. Dynamo uses partition keys and sort keys to uniquely identify and partion item in the database which allows for high scalability and throughput&lt;/p&gt;
&lt;p&gt;When working with traditional SQL databases a common operation is to update the value of a specific column without having to first fetch the entire row. DynamoDB offers us similar functionality using the AWS SDK&lt;/p&gt;
&lt;h2&gt;The Update Command&lt;/h2&gt;
&lt;p&gt;DynamoDB commands are simple objects that consist of a few different parts. When looking to update an item the following are relavant:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Key&lt;/code&gt; - which is an object that uniquely identifies an item in the database&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UpdateExpression&lt;/code&gt; - which is an expression that describes the upadate operation to be done using placeholders for attribute names and values (&lt;a href=&quot;https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html&quot; &gt;AWS Documentation - Update Expressions&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ExpressionAttributeNames&lt;/code&gt; - generic placehodlders for attribute names&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ExpresssionAtributeValues&lt;/code&gt; - generic placeholders for values&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When defining &lt;code&gt;UpdateExpression&lt;/code&gt; we use placeholders for the attribute names and values to prevent any escaping/unsupported character related issues. A common convention for this is to use &lt;code&gt;#&lt;/code&gt; at the start of attribute names and &lt;code&gt;:&lt;/code&gt; at the start of attribute values to make expressions a bit easier to negotiate, for example, if I wanted to set &lt;code&gt;name&lt;/code&gt; to &lt;code&gt;bob&lt;/code&gt; I would do &lt;code&gt;&amp;#39;#name&amp;#39;: &amp;#39;name&amp;#39;&lt;/code&gt; in the &lt;code&gt;ExpressionAttributeNames&lt;/code&gt; and &lt;code&gt;&amp;#39;#name&amp;#39;: &amp;#39;bob&amp;#39;&lt;/code&gt; in the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;DynamoDB uses an object representation that is a bit inconvenient to work with, we can use the &lt;code&gt;marshall&lt;/code&gt; and &lt;code&gt;unmarshall&lt;/code&gt; functions from &lt;code&gt;@aws-sdk/util-dynamodb&lt;/code&gt; to simplify things a bit but if you&amp;#39;d like to know more about the data format used you can look towards the end of this post&lt;/p&gt;
&lt;h2&gt;Our Example&lt;/h2&gt;
&lt;p&gt;For our example, imagine we have a table of user check-ins with data structured as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Item&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // partition key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  group&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // sort key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  username&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  status&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  checkIns&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    place&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    time&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Update an Attribute&lt;/h2&gt;
&lt;p&gt;We can use a bit of a generic structure to outline our data that we plan to update a single attribute. To do this, we can use the &lt;code&gt;SET&lt;/code&gt; command&lt;/p&gt;
&lt;p&gt;The update expression for setting a value will look like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;SET #attr = :value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Yup, that&amp;#39;s pretty much it as far as the expression goes, the actual names of the fields we want to update aren&amp;#39;t relevant here, instead they&amp;#39;re mentioned in the &lt;code&gt;ExpressionAtrributeNames&lt;/code&gt; and &lt;code&gt;ExpressionAttributeValues&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The overall command with all of that is as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDBClient } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@aws-sdk/client-dynamodb&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { marshall, unmarshall } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@aws-sdk/util-dynamodb&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; client&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; DynamoDBClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;bob&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; sk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; updateValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;available&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; command&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; UpdateItemCommand&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  TableName: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-table-name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Key: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;marshall&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    username: pk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    group: sk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  UpdateExpression: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;SET #attr = :value&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ExpressionAttributeNames: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;#attr&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;status&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ExpressionAtrributeValues: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;marshall&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;:value&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: updateValue,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And that&amp;#39;s pretty much the process for updating an attribute witha specific value&lt;/p&gt;
&lt;h2&gt;Append to a List Attribute That Exists&lt;/h2&gt;
&lt;p&gt;In the above data structure we have the &lt;code&gt;checkIns&lt;/code&gt; field which is a list of objects&lt;/p&gt;
&lt;p&gt;We can use the same method as above to define the &lt;code&gt;UpdateExpression&lt;/code&gt;, however this time we can use the &lt;code&gt;list_append&lt;/code&gt; function in our expression to state that we would like to append a value to&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;list_append&lt;/code&gt; function appends one list to another - this means that it needs two lists to operate on. To update a list we can just use itself as the first input and the new list as the second. The &lt;code&gt;UpdateExpression&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;SET #attr = list_append(#attr, :value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For our sake we only want to append a single item, so we can just wrap it in an array when we pass it on in the command. The command for the above update looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDBClient } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@aws-sdk/client-dynamodb&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { marshall, unmarshall } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@aws-sdk/util-dynamodb&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; client&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; DynamoDBClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;bob&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; sk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; updateValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  place: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;home&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  time: Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; command&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; UpdateItemCommand&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  TableName: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-table-name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Key: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;marshall&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    username: pk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    group: sk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  UpdateExpression: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;SET #attr = list_append(#attr, :value)&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ExpressionAttributeNames: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;#attr&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;checkIns&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ExpressionAtrributeValues: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;marshall&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // array since the update expression works on two lists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;:value&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [updateValue],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Append to a List Attribute That May Not Exist&lt;/h2&gt;
&lt;p&gt;In some cases, we can end up trying to append to an attribute that may not exist, under these circumstances we can use the &lt;code&gt;is_not_exists&lt;/code&gt; function that takes an attribute name and a fallback value and will return the fallback if the attribute does not exist in the item&lt;/p&gt;
&lt;p&gt;We can change the &lt;code&gt;UpdateExpression&lt;/code&gt; to make use of this as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;SET #attr = list_append(if_not_exists(#attr, :fallback), :value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the full command looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { DynamoDBClient } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@aws-sdk/client-dynamodb&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { marshall, unmarshall } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;@aws-sdk/util-dynamodb&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; client&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; DynamoDBClient&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;bob&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; sk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; updateValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  place: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;home&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  time: Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; command&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; UpdateItemCommand&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  TableName: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-table-name&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Key: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;marshall&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    username: pk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    group: sk,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  UpdateExpression:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;SET #attr = list_append(if_not_exists(#attr, :fallback), :value)&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ExpressionAttributeNames: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;#attr&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;checkIns&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ExpressionAtrributeValues: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;marshall&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;:value&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [updateValue],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // fallback to an empty array if the value does not exist before appending&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;#39;:fallback&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; client.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above expresson helps us append an item to the list while also providing a fallback for the case where the list item may not exist&lt;/p&gt;
&lt;h2&gt;A Note on Marshalled/Unmarshalled data&lt;/h2&gt;
&lt;p&gt;DynamoDB works with data in the &amp;quot;marshalled&amp;quot; form, which is an object representation for primitive data types (&lt;a href=&quot;https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html&quot; &gt;AWS Documentation - Attribute Value&lt;/a&gt;). Some examples of marshalled and unmarshalled data can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// STRING&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Unmarshalled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Marshalled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;S&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// NUMBER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Unmarshalled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;25&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Marshalled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;N&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;25&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// MAP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Unmarshalled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/// Marshalled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;M&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;quot;S&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Additional Resources&lt;/h2&gt;
&lt;p&gt;Speaking of DynamoDB updates, it looks like there&amp;#39;s a library for building queries which seems promising and may bwe worth taking a look at called &lt;a href=&quot;https://electrodb.dev/en/core-concepts/introduction/&quot; &gt;ElectroDB&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Draggable Div with XState and React</title><link>https://nabeelvalley.co.za/blog/2023/31-01/xstate-draggable-div.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2023/31-01/xstate-draggable-div.html</guid><description>A simple example of using XState with UI Events to build interactivity</description><pubDate>Tue, 31 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Draggable Div with XState and React&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Why State Management&lt;/h2&gt;
&lt;p&gt;Recently I&amp;#39;ve been interested in understanding non-standard user interactions and about how different applications develop this functionality. A particularly good example for me has been looking into the codebase for &lt;a href=&quot;https://www.tldraw.com/&quot; &gt;TLDraw&lt;/a&gt; where I ran into state machines&lt;/p&gt;
&lt;p&gt;Now, I&amp;#39;ve played around with a few state machine libraries and I&amp;#39;m fairly familiar with them and have implemented some fairly simple examples for working with multi-step forms and the like, but I haven&amp;#39;t really used them in the specific context of designing state&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.state-designer.com&quot; &gt;State Designer Library&lt;/a&gt; mentions the idea of &lt;a href=&quot;https://www.state-designer.com/designing-state&quot; &gt;Designing State&lt;/a&gt; which suggests that the design of how the user interface should work and the implementation of it should be treated as independent, in order to do so, we should design the states that we would like to work with separately from the UI that implements the state&lt;/p&gt;
&lt;p&gt;This provides us with a decent abstraction which should make things about state a lot less tangled and easier to reason about&lt;/p&gt;
&lt;h3&gt;XState&lt;/h3&gt;
&lt;p&gt;State management libraries provide us with a set of abstractions and tools for designing state. There are a few that are commonly used, of which I&amp;#39;ll be using &lt;a href=&quot;https://xstate.js.org/&quot; &gt;XState&lt;/a&gt; in this post. XState has pretty good TypeScript support as well as some great tooling for visualizing and designing state on &lt;a href=&quot;https://stately.ai&quot; &gt;Stately&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;For this post I&amp;#39;ve chosen to build a simple draggable div component that makes use of XState. The idea here was to get a feel for the library and see how it can be used to tackle problems around UI interaction&lt;/p&gt;
&lt;h3&gt;Visualizing the State&lt;/h3&gt;
&lt;p&gt;Defining the state can be done using the XState visual editor that can be used in VSCode or Stately, this is useful because it lets you visualize different ways that the state can be represented in a relatively low-friction setting&lt;/p&gt;
&lt;p&gt;The structure I&amp;#39;ve decided on for the representing my component&amp;#39;s state can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.6436285097192225&quot; orientation=&quot;horizontal&quot; alt=&quot;draggable-state-diagram&quot; src=&quot;/optimized-images/public/content/blog/2023/31-01/draggable-state-diagram.webp&quot; &gt;&lt;/p&gt;
&lt;h3&gt;State Machine Code&lt;/h3&gt;
&lt;p&gt;The code for the above state machine, with some added type information, can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Draggable.machine.ts&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { createMachine, assign } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;xstate&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Position&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Delta&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  dx&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  dy&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Focus&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  focused&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; machine&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createMachine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    schema: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      context: {} &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      events: {} &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;MOVE&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;; position: Delta }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;FOCUS&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;BLUR&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    initial: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;inactive&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    states: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      inactive: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        on: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          FOCUS: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      active: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        on: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          MOVE: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            target: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            internal: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            actions: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;updatePosition&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          BLUR: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;inactive&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    actions: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      updatePosition: &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;assign&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;context&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        x: event.position.dx &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (context.x &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        y: event.position.dy &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (context.y &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      })),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above, we can also see the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;initial&lt;/code&gt; state that is &lt;code&gt;inactive&lt;/code&gt; with an event of &lt;code&gt;FOCUS&lt;/code&gt; which sets the state to &lt;code&gt;active&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;active&lt;/code&gt; state that has an internal event of &lt;code&gt;MOVE&lt;/code&gt; which will trigger the &lt;code&gt;updatePosition&lt;/code&gt; action and an event of &lt;code&gt;BLUR&lt;/code&gt; which sets the state to &lt;code&gt;inactive&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;There is a &lt;code&gt;context&lt;/code&gt; that will store the coordinates of the dragged element&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;actions&lt;/code&gt; object which has an action called &lt;code&gt;updatePosition&lt;/code&gt; which assigns the context to the new position&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can also see that in the schema the type of &lt;code&gt;events&lt;/code&gt; is specified. This makes it so that XState can infer the type of &lt;code&gt;event&lt;/code&gt; passed to the &lt;code&gt;updatePosition&lt;/code&gt; function&lt;/p&gt;
&lt;h3&gt;Attach the State to the UI&lt;/h3&gt;
&lt;p&gt;In order to move from one state to another we use the &lt;code&gt;send&lt;/code&gt; method from XState&lt;/p&gt;
&lt;p&gt;To use a state machine in React we use the &lt;code&gt;useMachine&lt;/code&gt; hook from XState:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Draggable.tsx&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { useMachine } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;@xstate/react&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; React &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;react&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { machine } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;./Draggable.machine&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DraggableProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  children&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; React&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ReactNode&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Draggable&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DraggableProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;current&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; useMachine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(machine);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // rest of component&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we can use the &lt;code&gt;current&lt;/code&gt; to figure out if we are in an active state so that we can do some styling based on that:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Draggable.tsx&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isActive&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; current.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;matches&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And lastly we can hook up the UI Events to the state machine:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Draggable.tsx&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;tsx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Draggable&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; DraggableProps&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;current&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; useMachine&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(machine)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isActive&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; current.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;matches&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{ position: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;relative&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        onMouseDown&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;FOCUS&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        onMouseUp&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;BLUR&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        onMouseLeave&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;BLUR&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        onMouseMove&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ev&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;          send&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;MOVE&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            position: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;              dx: ev.movementX,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;              dy: ev.movementY,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;            },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;        style&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;={&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          position: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;absolute&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          backgroundColor: isActive &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;skyblue&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; :&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;red&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          userSelect: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;none&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          top: current.context.y,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          left: current.context.x,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          padding: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;20&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        {&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;children&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above will result in a draggable div like so:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://replit.com/@nabeelvalley/DraggableDiv?v=1&quot; &gt;Repl.it link&lt;/a&gt;&lt;/p&gt;
&lt;iframe frameborder=&quot;0&quot; width=&quot;100%&quot; height=&quot;500px&quot; src=&quot;https://replit.com/@nabeelvalley/DraggableDiv?embed=true&quot; &gt;&lt;/iframe&gt;&lt;h3&gt;Possible Improvements&lt;/h3&gt;
&lt;p&gt;If you play around with the above example you&amp;#39;ll probably notice that it&amp;#39;s not perfect. Though the states we&amp;#39;ve defined are correct,the complexity in mapping the UI events becomes apparent, as well as the various edge cases that may arise around how DOM events fire in response to user interaction&lt;/p&gt;
&lt;p&gt;Though I don&amp;#39;t aim to solve all of these points for the sake of the example, it&amp;#39;s worth pointing out as a source of exploration. Some possible solutions that may help are things like changing where we listen to specific events, for example listening to the &lt;code&gt;mouseUp&lt;/code&gt; events on only the wrapper and not the draggable component, or changing which specific events we&amp;#39;re listening to&lt;/p&gt;
&lt;p&gt;The idea is that the handling of the UI events is now separated from the actual state management which should make fixing interaction bugs simpler while also decoupling our state from any specific implementation of the UI&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;For more information, you can take a look at the &lt;a href=&quot;https://xstate.js.org/docs/&quot; &gt;XState Documentation&lt;/a&gt; or the &lt;a href=&quot;https://www.youtube.com/playlist?list=PLvWgkXBB3dd4ocSi17y1JmMmz7S5cV8vI&quot; &gt;XState YouTube Course&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition, I also have a more complex example using XState for building a &lt;a href=&quot;https://replit.com/@nabeelvalley/XStateTodoApp&quot; &gt;Todo App&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 35, year 2024 - datetimes and logic programming</title><link>https://nabeelvalley.co.za/blog/2024/01-09/week-35-datetimes-and-logic-programming.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/01-09/week-35-datetimes-and-logic-programming.html</guid><pubDate>Sun, 01 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 35, year 2024 - datetimes and logic programming&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;what i&amp;#39;m working on&lt;/h2&gt;
&lt;p&gt;after many months i spent some time on a project i&amp;#39;m working with a friend to build a sort of &amp;quot;home cloud&amp;quot; platform. it&amp;#39;s always weird coming to a project having no clue where you left it and trying to stitch some context from whatever happens when you run &lt;code&gt;pnpm start&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;i also found a handy little way to &lt;a href=&quot;https://nabeelvalley.co.za/blog/2024/28-08/open-terminal-links-in-vscode/&quot; &gt;open links from the vscode terminal&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;p&gt;i spent a little time learning about logic programming and came across an interesting talk about some of the challenges when writing libraries&lt;/p&gt;
&lt;h3&gt;prolog&lt;/h3&gt;
&lt;p&gt;a logic programming language - super weird but &lt;a href=&quot;https://www.youtube.com/watch?v=G_eYTctGZw8&quot; &gt;this talk on prolog by Michael Hendricks&lt;/a&gt; helped shed some light on how this is something that&amp;#39;s actually usable&lt;/p&gt;
&lt;h3&gt;standard libraries&lt;/h3&gt;
&lt;p&gt;i also came across a great talk about some challenges when maintaining something like &lt;a href=&quot;https://www.youtube.com/watch?v=lxoKilLSJ4k&quot; &gt;the kotlin standard library by Vsevolod Tolstopyatov&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 31, year 2024 - webgpu and parsers</title><link>https://nabeelvalley.co.za/blog/2024/02-08/week-31-webgpu-and-parsers.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/02-08/week-31-webgpu-and-parsers.html</guid><pubDate>Fri, 02 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 31, year 2024 - webgpu and parsers&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;welcome&lt;/h2&gt;
&lt;p&gt;since this is my first post in this format i figured i should just say hey! this series will be a bit of a braindump for project updates and links to things i found this week&lt;/p&gt;
&lt;h2&gt;what i&amp;#39;m working on&lt;/h2&gt;
&lt;p&gt;right now i&amp;#39;m the concept of a photo editing app that uses shaders for applying image effects, the initial concept seems to be promising but there&amp;#39;s still a fair amount of work to be done before i can have anything even remotely usable&lt;/p&gt;
&lt;p&gt;i also had an excuse to use git bisect in a new and interesting way and made some additions to &lt;a href=&quot;https://nabeelvalley.co.za/docs/random/git#find-bad-commits-using-bisect&quot; &gt;my git notes&lt;/a&gt; about using the &lt;code&gt;—first-parent&lt;/code&gt; and &lt;code&gt;replay &lt;/code&gt;functionality&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;ts-parsec&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;i&amp;#39;ve been pretty invested in parser combinators recently and have been playing around with the &lt;a href=&quot;https://github.com/microsoft/ts-parsec&quot; &gt;ts-parsec library&lt;/a&gt; and it&amp;#39;s been a pretty fun time. for a general idea of what these things are all about you can take a look at &lt;a href=&quot;https://nabeelvalley.co.za/blog/2024/20-07/parser-combinators-and-gleam/&quot; &gt;my blog post on parser combinators&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;WebGPU&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API&quot; &gt;webgpu&lt;/a&gt; is the &amp;quot;new&amp;quot; way to create shaders on the web and comes with a new javsacript API and a &lt;a href=&quot;https://www.w3.org/TR/WGSL/&quot; &gt;new language called wgsl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;the api is a bit more complex than the one for webgl but still reasonably manageable if you take a read through the &lt;a href=&quot;https://webgpufundamentals.org/&quot; &gt;webgpu fundamentals site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;additionally, i found a few great resources for using webgpu for image filters, namely work by &lt;a href=&quot;https://alain.xyz/blog/image-editor-effects&quot; &gt;Alain Galvan&lt;/a&gt; and &lt;a href=&quot;https://maximmcnair.com/#&quot; &gt;Maxim McNair&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Conditionally Protect Properties in Typescript</title><link>https://nabeelvalley.co.za/blog/2024/03-12/conditional-protection.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/03-12/conditional-protection.html</guid><description>Using type-guards to protect access to values</description><pubDate>Tue, 03 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Conditionally Protect Properties in Typescript&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Type Guards&lt;/h2&gt;
&lt;p&gt;So, type guards are really handy in Typescript as they let us check if something meets a certain requirement before moving along, for example, given the following user type:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  active&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  age&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can define a type guard that checks if the user is fully is &lt;code&gt;active&lt;/code&gt; before allowing certain things. To do this we usually use a type guard, that looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ActiveUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; User&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;active&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; isActive&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;base&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Partial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;User&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; base&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ActiveUser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  !!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(base.active &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; base.age &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; base.name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The important thing in a type guard is that it takes something of one type and asserts something about that type, e.g. that it is an &lt;code&gt;ActiveUser&lt;/code&gt; in the above. This is done by returning a boolean, if it is &lt;code&gt;true&lt;/code&gt; then the assertion applies, otherwise it does not&lt;/p&gt;
&lt;p&gt;And normally, we would use it like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isActive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(user)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // do stuff that can only be done with an active user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// outside of this scope users are not active&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Gaurded Class&lt;/h2&gt;
&lt;p&gt;The above solution is usually good enough. But it&amp;#39;s also possible to couple the types of these checks while not providing direct access to the underlying object. This is useful in cases where we may want to restrict access to some functionality unless a certain set of checks pass&lt;/p&gt;
&lt;p&gt;To do this, we can encapsulate the value and check into a class, e.g. the &lt;code&gt;Guarded&lt;/code&gt; class below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Guarded&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Unsafe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Safe&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Unsafe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Unsafe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    private&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; safe&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Unsafe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Safe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Type guard that grants access to the wrapped `value`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  isSafe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; is&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Safe } {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;safe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above, we define a &lt;code&gt;Guarded&lt;/code&gt; class htat has a type of a &lt;code&gt;Safe&lt;/code&gt; and &lt;code&gt;Unsafe&lt;/code&gt; value. These generics can be inferred by the arguments provided to &lt;code&gt;constructor&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Next, we define the &lt;code&gt;isSafe&lt;/code&gt; method on the class that is a gaurd that says something about &lt;code&gt;this&lt;/code&gt; which is the instance itself.&lt;/p&gt;
&lt;p&gt;So, we can use &lt;code&gt;Guarded&lt;/code&gt; to wrap something that we want to only make available under certain scenarios:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; guarded&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Guarded&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value, isActive);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (guarded.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;isSafe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Can access value here&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, guarded.value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// guarded.value; // error: Property &amp;#39;value&amp;#39; is protected and only accessible within class &amp;#39;Guarded&amp;lt;Unsafe, Safe&amp;gt;&amp;#39; and its subclasses.ts(2445)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Can&amp;#39;t access value here&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;What&amp;#39;s great is that this &lt;code&gt;safe&lt;/code&gt; check is re-run whenever we want to access the &lt;code&gt;value&lt;/code&gt;, this means that we can make certain properties available based on some other state that can be checked in the &lt;code&gt;safe&lt;/code&gt; method&lt;/p&gt;
&lt;p&gt;This approach means that at compile time the Typescript compiler will check that we are only accessing &lt;code&gt;value&lt;/code&gt; within a context that we have defined to be okay by way of our &lt;code&gt;isSafe&lt;/code&gt; method. Additionally, since we can specify the behavior of &lt;code&gt;isSafe&lt;/code&gt; we end up with a a check that works at the intersection of compile-time and runtime &lt;/p&gt;
&lt;h2&gt;Note&lt;/h2&gt;
&lt;p&gt;The first idea of Type Guards is quite often used and should be good enough for normal use&lt;/p&gt;
&lt;p&gt;Withr egards to the &lt;code&gt;Guarded&lt;/code&gt; idea, use with caution. The idea here it to create a certain safety for consumers of some code, but this is at the expense of complexity and should be used with care. Outside of the &amp;quot;can it be done&amp;quot; discussion I haven&amp;#39;t really had much use for something like this since usually a normal type guard is good enough&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Show Children when Parent is Hidden with CSS</title><link>https://nabeelvalley.co.za/blog/2024/04-04/css-show-children-when-parent-hidden.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/04-04/css-show-children-when-parent-hidden.html</guid><description>Make the children of an HTML element visible when the parent element is hidden</description><pubDate>Thu, 04 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Show Children when Parent is Hidden with CSS&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;When working with HTML we sometimes have a case where we want to view child items of an HTML element while the parent element itself is hidden&lt;/p&gt;
&lt;p&gt;Normally when trying to hide or show some elements, we would apply &lt;code&gt;display:none&lt;/code&gt; and move on. However, we may run into a case where we want to make a specific child visible while keeping the remaining content hidden, so, we might try to add the following to the child &lt;code&gt;display:block&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We will quickly see that this solution doesn&amp;#39;t work. Another thing we might trying to play with the opacity of the items but this doesn&amp;#39;t really solve our problem either&lt;/p&gt;
&lt;p&gt;The solution to this is the &lt;code&gt;visibility&lt;/code&gt; property&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;According to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/visibility&quot; &gt;the MDN Documentation on Visibility&lt;/a&gt;: &amp;quot;The visibility CSS property shows or hides an element without changing the layout of a document.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The MDN definition brings up an important note - the visibility property does not change the layout of the document - this means the hidden elements will still take up space on the screen, which is different to the behaviour of &lt;code&gt;display:none&lt;/code&gt;. However, we can mitigate that in other ways if we need to deepending on what we&amp;#39;re trying to do&lt;/p&gt;
&lt;p&gt;We can use the &lt;code&gt;visibility&lt;/code&gt; property to get what we want. For our example let&amp;#39;s use a &lt;code&gt;ol&lt;/code&gt; with some children, however, we want anything inside of our list to be hidden other than a specific child&lt;/p&gt;
&lt;p&gt;The HTML we have is as follows:&lt;/p&gt;
&lt;site-snippet-preview&gt;&lt;div&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;css-visibility/css-visibility.css&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.hide&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--hide-display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--hide-visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.show&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--show-display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--show-visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;visible&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.example&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;rem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--color-on-base&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--color-base&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;css-visibility/CSSVisibility.html&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;before hidden&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ol&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hide&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;show&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item 2&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item 3&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ol&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;after hidden&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;example&quot; &gt;
  &lt;div&gt;before hidden&lt;/div&gt;

  &lt;ol class=&quot;hide&quot; &gt;
    &lt;li&gt;Item 1&lt;/li&gt;
    &lt;li class=&quot;show&quot; &gt;Item 2&lt;/li&gt;
    &lt;li&gt;Item 3&lt;/li&gt;
  &lt;/ol&gt;

  &lt;div&gt;after hidden&lt;/div&gt;
&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;&lt;style&gt;@scope {.hide {
  display: var(--hide-display);
  visibility: var(--hide-visibility, hidden);
}

.show {
  display: var(--show-display);
  visibility: var(--show-visibility, visible);
}

.example {
  padding: 1rem;
  background-color: var(--color-on-base);
  color: var(--color-base);
}}&lt;/style&gt;&lt;/div&gt;&lt;/site-snippet-preview&gt;&lt;p&gt;It&amp;#39;s also important to note that the content before and after the list are not visible but they still take up space&lt;/p&gt;
&lt;p&gt;You can play around with the CSS properties below to see how the influence the overall styling:&lt;/p&gt;
&lt;site-snippet-preview&gt;&lt;div&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;css-visibility/css-visibility.css&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.hide&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--hide-display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--hide-visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.show&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--show-display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--show-visibility&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;visible&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.example&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;rem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--color-on-base&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;--color-base&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;css-visibility/CSSVisibility.html&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;before hidden&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ol&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hide&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;show&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item 2&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Item 3&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ol&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;after hidden&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;div class=&quot;example&quot; &gt;
  &lt;div&gt;before hidden&lt;/div&gt;

  &lt;ol class=&quot;hide&quot; &gt;
    &lt;li&gt;Item 1&lt;/li&gt;
    &lt;li class=&quot;show&quot; &gt;Item 2&lt;/li&gt;
    &lt;li&gt;Item 3&lt;/li&gt;
  &lt;/ol&gt;

  &lt;div&gt;after hidden&lt;/div&gt;
&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;&lt;style&gt;@scope {.hide {
  display: var(--hide-display);
  visibility: var(--hide-visibility, hidden);
}

.show {
  display: var(--show-display);
  visibility: var(--show-visibility, visible);
}

.example {
  padding: 1rem;
  background-color: var(--color-on-base);
  color: var(--color-base);
}}&lt;/style&gt;&lt;/div&gt;&lt;/site-snippet-preview&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>View Transitions and an Astro Presentation Framework</title><link>https://nabeelvalley.co.za/blog/2024/06-03/astro-slides.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/06-03/astro-slides.html</guid><description>Easily create presentations from your existing markdown content</description><pubDate>Wed, 06 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;View Transitions and an Astro Presentation Framework&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Well, since this is a post about building a presentation framework within your Astro site, it may be worth mentioning that you can view this page as a presentation using the below button:&lt;/p&gt;
&lt;site-presentation&gt;&lt;/site-presentation&gt;&lt;site-presentation-slide centered=&quot;&quot; &gt;&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;/site-presentation-slide&gt;&lt;site-presentation-slide centered=&quot;&quot; &gt;&lt;blockquote&gt;
&lt;p&gt;I&amp;#39;m kind of lazy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;I had to put together a little presentation based on something I&amp;#39;ve written about previously and wanted a lazy way to reuse my existing content while also making the resulting presentation available on my website&lt;/p&gt;
&lt;p&gt;Overall, these are the requirements I had in mind:&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h3&gt;My Requirements&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Not require any additional build process&lt;/li&gt;
&lt;li&gt;Work with Markdown or MDX so I can include it in my website easily&lt;/li&gt;
&lt;li&gt;Have a small learning curve&lt;/li&gt;
&lt;li&gt;Integrate flexibly with my existing content - pages should be able to be very easily converted to slides&lt;/li&gt;
&lt;/ol&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;So I investigated a few solutions:&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h3&gt;Existing Slide Solutions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Just a markdown doc&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://revealjs.com/&quot; &gt;Reveal.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jxnblk/mdx-deck&quot; &gt;MDX Deck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/FormidableLabs/spectacle&quot; &gt;Spectacle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Plain&amp;#39; ol&amp;#39; HTML&lt;/li&gt;
&lt;li&gt;PowerPoint??&lt;/li&gt;
&lt;/ol&gt;
&lt;/site-presentation-slide&gt;&lt;site-presentation-slide centered=&quot;&quot; &gt;&lt;blockquote&gt;
&lt;p&gt;The existing solutions just don&amp;#39;t work for my case&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Now, it&amp;#39;s not that they&amp;#39;re not good - most of them are pretty great and have some features that I would like to use if this were some once-off throwaway presentation, but since I would like to refer back to and manage the way I want they&amp;#39;re not really suitable&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I also didn&amp;#39;t want to style everything from scratch or write lots of HTML everywhere&lt;/p&gt;
&lt;/blockquote&gt;
&lt;site-presentation-slide centered=&quot;&quot; &gt;&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;blockquote&gt;
&lt;p&gt;Build it myself. Obviously&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/site-presentation-note&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Instead of just looking at the existing options, I instead chose to build a library/framework that would work with my existing Astro site while keeping the implementation relatively minimal and just depending on plain CSS, Javascript, MDX, and Astro to get the job done&lt;/p&gt;
&lt;site-presentation-slide&gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;h3&gt;Use Existing Tooling&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Javascript (Typescript)&lt;/li&gt;
&lt;li&gt;MDX&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Facilitated by - not coupled to - Astro&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/site-presentation-note&gt;
&lt;/site-presentation-slide&gt;&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;So, since I&amp;#39;m building it myself, that means code - and that&amp;#39;s what we&amp;#39;re going to look at&lt;/p&gt;
&lt;h3&gt;The API&lt;/h3&gt;
&lt;p&gt;I wanted to keep the API relatively simple. It should work with existing markdown content and allow me to delineate a slide in a way that can be easily read from the DOM so as to minimize the amount of build-time processing I need to do as well as minimize how much markup I need to write. For this purpose, I decided that I want it to fit into an MDX document like so:&lt;/p&gt;
&lt;site-presentation-slide centered=&quot;&quot; &gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;h3&gt;The API&lt;/h3&gt;
&lt;/site-presentation-note&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;mdx&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Button to launch the presentation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;site-presentation&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;... Existing page content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;site-presentation-slide&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-light-font-weight:bold;--shiki-dark:#91CBFF;--shiki-dark-font-weight:bold&quot; &gt;## Heading for Slide&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;Some content for the slide&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;```&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;I am a code block&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;&amp;gt; And literally any other markdown content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;&amp;lt;/site-presentation-slide&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Hiven the above, I had a high level idea that I would need two parts to this - firstly I want to use the &lt;code&gt;Slide&lt;/code&gt; component to give me something to latch onto in the HTML that I can manipulate, secondly I know I would need some kind of component that would control the overall presentation state, I called that &lt;code&gt;Presentation&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;The &lt;code&gt;Slide&lt;/code&gt; Component&lt;/h3&gt;
&lt;p&gt;The Slide component is simply a wrapper that includes content in an HTML section with a class &lt;code&gt;presentation-slide&lt;/code&gt; which will contain the contents of a slide&lt;/p&gt;
&lt;site-presentation-slide centered=&quot;&quot; &gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;h3&gt;The &lt;code&gt;Slide&lt;/code&gt; Component&lt;/h3&gt;
&lt;/site-presentation-note&gt;&lt;p&gt;&lt;code&gt;components/Slide.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;presentation-slide&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;slot /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/section&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;h3&gt;The &lt;code&gt;Presentation&lt;/code&gt; Component&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Presentation&lt;/code&gt; component needs to do a few different things:&lt;/p&gt;
&lt;site-presentation-slide centered=&quot;&quot; &gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;h3&gt;The &lt;code&gt;Presentation&lt;/code&gt; Component&lt;/h3&gt;
&lt;/site-presentation-note&gt;&lt;ol&gt;
&lt;li&gt;Hide presentation until enabled&lt;/li&gt;
&lt;li&gt;Allow navigation of slides&lt;/li&gt;
&lt;li&gt;Render slide content above existing page&lt;/li&gt;
&lt;li&gt;Manage transitions between slide pages&lt;/li&gt;
&lt;/ol&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Firstly, we can just take a look at the HTML that we will render contains a few basic elements as well as a script tag that grabs a reference to these elements. The &lt;code&gt;presentation-hidden&lt;/code&gt; class is used for hiding or showing the presentation when active/inactive:&lt;/p&gt;
&lt;site-presentation-slide centered=&quot;&quot; &gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;h3&gt;Basic Elements&lt;/h3&gt;
&lt;/site-presentation-note&gt;&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;presentation-button&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;presentation-hidden&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;button&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  Start Presentation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;presentation-container&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;presentation-hidden presentation-overflow-hidden&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;presentation-content&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;No slides found on page&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; button&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;presentation-button&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HTMLButtonElement&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; container&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;presentation-container&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HTMLDivElement&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;presentation-content&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; HTMLDivElement&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Next, we can grab the actual slide content by using the &lt;code&gt;presentation-slide&lt;/code&gt; class we defined earlier:&lt;/p&gt;
&lt;site-presentation-slide centered=&quot;&quot; &gt;&lt;h3&gt;Get Slides&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slides &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Array.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;.presentation-slide&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;el&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; el.outerHTML,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Once we have the content of the slides and a variable to track which slide we are on, we can define a function that will set the slide content. This will set the &lt;code&gt;innerHTML&lt;/code&gt; of the &lt;code&gt;content&lt;/code&gt; element to the &lt;code&gt;slide&lt;/code&gt; that is active. We can handle this by first defining some utilities for grabbing the next and previous slides as well as mapping a key code to the function that will resolve the next slide&lt;/p&gt;
&lt;site-presentation-slide&gt;
&lt;site-presentation-note class=&quot;slide-only&quot; &gt;&lt;h2&gt;Slide Utilities&lt;/h2&gt;
&lt;/site-presentation-note&gt;&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; nextSlide&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slides.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slide&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; prevSlide&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slide&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; keyHandlers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ArrowRight: nextSlide,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ArrowLeft: prevSlide,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Next, we can define what it means for us to start and end a presentation. For this example, starting a presentation will remove the &lt;code&gt;presentation-hidden&lt;/code&gt; class from the main wrapper so we can make the presentation visible on the page as well as set the content to the current slide index (we initialized this to &lt;code&gt;0&lt;/code&gt; above)&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h2&gt;Start and End Presentation&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; startPresentation&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  container.classList.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;remove&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;presentation-hidden&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (slides.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slides[slide]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; endPresentation&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  container.classList.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;add&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;presentation-hidden&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;We set the content to &lt;code&gt;slide&lt;/code&gt; instead of &lt;code&gt;0&lt;/code&gt; so that we can pause and continue the presentation if we wanted to&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Next, hook up some event handlers so that we can have a method for controlling our presentation:&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h3&gt;Wiring things up&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// If there is no presentation on the page then we don&amp;#39;t initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (slides.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  button.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, startPresentation)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  window.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;keyup&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ev&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isEscape&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ev.key &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Escape&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (isEscape) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      endPresentation&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getSlide&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; keyHandlers[ev.key]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;getSlide) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nextSlide&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getSlide&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nextSlide) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nextSlide&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    content.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slides[slide]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;blockquote&gt;
&lt;p&gt;In the above, the left and right arrows are used to navigate slides and the escape key is used to end the presentation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next up, we need to add some CSS to make the slides pin to the root of our application above everything else so that you can actually use this:&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h3&gt;Styling&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; is:global&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .presentation-overflow-hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    overflow&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .presentation-hidden&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;none&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  #presentation-container&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    z-index&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;fixed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    top&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    overflow&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;auto&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    backdrop-filter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;blur&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;50&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;#0000007d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  #presentation-content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    display&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;flex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    flex-direction&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;column&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    background-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;black&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;white&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    box-sizing&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;border-box&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    min-height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;vh&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;rem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;And that&amp;#39;s pretty much it for the core implementation. One other piece of fanciness that I wanted to add was the ability to make an actual slide transition. To do this I decided to use the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API&quot; &gt;View Transitions API&lt;/a&gt; and found a few nice references on the &lt;a href=&quot;https://philnash.github.io/unnecessary-view-transitions&quot; &gt;Unnecessary View Transitions API List&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In order to use this you need to have the feature enabled in your browser at the moment but it should be stable soon (I hope)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For this implementation, we will need to have different animations for the case where we are moving forwards or backwards. In order to do this, we will define some classes as part of our keyboard handler resolution that we will append to the &lt;code&gt;presentation-container&lt;/code&gt;:&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h3&gt;View Transitions&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nextClass&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;presentation-next&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; prevClass&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;presentation-prev&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; transitionClasses&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [nextClass, prevClass]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; keyHandlers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ArrowRight: [nextClass, nextSlide],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ArrowLeft: [prevClass, prevSlide],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Then, we will update our event handling logic to set these classes on the &lt;code&gt;contaienr&lt;/code&gt;&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h4&gt;Setting the Classes&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;transitionClass&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;getSlide&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; handler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;content.classList.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;remove&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;transitionClasses)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;content.classList.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;add&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(transitionClass)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nextSlide&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getSlide&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nextSlide) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Then, instead just setting the &lt;code&gt;content.innerHTML&lt;/code&gt; directly, we do it within the &lt;code&gt;document.startViewTransition&lt;/code&gt; callback which will be what handles the state transition between the content leaving the DOM and the new content that is entering the DOM&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that the &lt;code&gt;startViewTransition&lt;/code&gt; API is experimental and typescript may complain, you will need to install &lt;code&gt;@types/dom-view-transitions&lt;/code&gt; which will provide the type definition you need to use this API&lt;/p&gt;
&lt;/blockquote&gt;
&lt;site-presentation-slide&gt;&lt;h4&gt;Starting the Transition&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;startViewTransition&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  slide &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nextSlide&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  content.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; slides[slide]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;The last thing we need to do is define the view transitions for when the content enters and exists the DOM. The transitions are defined in the &lt;code&gt;style&lt;/code&gt; tag of our component as follows:&lt;/p&gt;
&lt;p&gt;Firstly we need to&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h4&gt;Animations&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@keyframes&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; slide-out-right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  0%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  15%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  85%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  100%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@keyframes&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; slide-out-left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  0%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  15%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  85%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;-100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  100%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;translateX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;-100&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;scale&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;The above defines two basic animations that we will use for our transitions. We define an animation that moves an element off the screen to the right called &lt;code&gt;slide-out-right&lt;/code&gt; and another to move it to the left called &lt;code&gt;slide-out-left&lt;/code&gt;. These animations can also be reversed to slide content in from the right or left respectively&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;p&gt;For the &amp;quot;Next&amp;quot; animation we need to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Slide the old content to the left&lt;/li&gt;
&lt;li&gt;Slide the new content from the right&lt;/li&gt;
&lt;/ol&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;In the below we set that the &lt;code&gt;presentation-next&lt;/code&gt; class defines a &lt;code&gt;view-transition-name&lt;/code&gt; called &lt;code&gt;next&lt;/code&gt;. Then, we define the transitions for the &lt;code&gt;old&lt;/code&gt; and &lt;code&gt;new&lt;/code&gt; content that applies to the &lt;code&gt;next&lt;/code&gt; transition name as an Animation. We are referencing a &lt;code&gt;slide-out-right&lt;/code&gt; and &lt;code&gt;slide-out-left&lt;/code&gt; animations which we defined previously:&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h4&gt;CSS Transitions&lt;/h4&gt;
&lt;p&gt;Below is the transition for moving to the next slide&lt;/p&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.presentation-next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  view-transition-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: next;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;::view-transition-old(next) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: slide-out-left &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; linear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;::view-transition-new(next) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: slide-out-right &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; linear&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;view-transition-old&lt;/code&gt; refers to content that is being removed from the DOM, &lt;code&gt;view-transition-new&lt;/code&gt; refers to the content that is being added to the DOM&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/site-presentation-slide&gt;&lt;p&gt;Lastly, the implementation for the &lt;code&gt;presentation-prev&lt;/code&gt; we can reuse the same animations for moving left or right as we defined previously, but change the directions as needed for the relevant section&lt;/p&gt;
&lt;p&gt;&lt;code&gt;components/Presentation.astro&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.presentation-prev&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  view-transition-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: prev;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;::view-transition-old(prev) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: slide-out-right &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; linear&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;::view-transition-new(prev) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: slide-out-left &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;s&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; linear&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; reverse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And yes, that&amp;#39;s a fair amount of code. All-in it&amp;#39;s about 200 lines - most of which is the CSS for the transition though. Generally the implementation is pretty straightforward and should be relatively easy to tweak to match the vibe of your website without adding any dependency bloat.&lt;/p&gt;
&lt;p&gt;As it stands right now the implementation is pretty simple but leaves a lot of space to be extended&lt;/p&gt;
&lt;site-presentation-slide&gt;&lt;h3&gt;Added since this post was written&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Presenter mode with some kind of synchronized state for multiple monitors (LocalStorage?)&lt;/li&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Progress tracking&lt;/li&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Support for non-static components&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Future Ideas&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Presenter notes and preview of next slide&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Make this a library so other people can use it with less copy pasta&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; More transitions and styling possibilities&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Dynamic code blocks/customizable transitions (&lt;a href=&quot;https://github.com/pomber/code-surfer&quot; &gt;Code Surfer&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot; &gt; Automatic zooming&lt;/li&gt;
&lt;/ul&gt;
&lt;/site-presentation-slide&gt;&lt;site-presentation-slide&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We used some interesting CSS here and overall we can see that it&amp;#39;s not always a huge amount of work to write your own implementation of something.&lt;/p&gt;
&lt;/site-presentation-slide&gt;&lt;h2&gt;Update 17 June 2026&lt;/h2&gt;
&lt;p&gt;This component has since been massively updated and now uses web components on the side - take at the source in your browser for the latest iteration!&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API&quot; &gt;MDN View Transitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/docs/web-platform/view-transitions&quot; &gt;Smooth and simple transitions with the View Transitions API &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://philnash.github.io/unnecessary-view-transitions&quot; &gt;Unnecessary View Transitions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 40, year 2024 - paper and pictures</title><link>https://nabeelvalley.co.za/blog/2024/06-10/week-40-paper-and-pictures.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/06-10/week-40-paper-and-pictures.html</guid><pubDate>Sun, 06 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 40, year 2024 - paper and pictures&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;firstly, a small sadness - i missed the past two posts due to my vacation, but on the other hand i guess i had a vacation so that works out i suppose&lt;/p&gt;
&lt;h2&gt;what i&amp;#39;m working on&lt;/h2&gt;
&lt;p&gt;spent the past week mostly working on a talk that i&amp;#39;m (hopefully) going to be doing towards the end of the month, i also gave a little &lt;a href=&quot;https://nabeelvalley.co.za/talks/2024/03-10/a-nu-er-shell/&quot; &gt;intro presentation on nushell&lt;/a&gt; that I think went pretty well&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;p&gt;this week i&amp;#39;m going to be sharing a few sites i&amp;#39;ve come across of people doing interesting things&lt;/p&gt;
&lt;h3&gt;paper engineering&lt;/h3&gt;
&lt;p&gt;Julia Yus makes really interesting things out of paper and &lt;a href=&quot;https://juliayus.com&quot; &gt;her portfolio&lt;/a&gt; is a really window into the things that you wouldn&amp;#39;t have thought were possible with paper&lt;/p&gt;
&lt;h3&gt;fashion photography&lt;/h3&gt;
&lt;p&gt;George Morris is a London based photographer and director with &lt;a href=&quot;https://www.george-morris.com&quot; &gt;a portfolio of images and videos&lt;/a&gt; focused on some campaigns that he&amp;#39;s done&lt;/p&gt;
&lt;h3&gt;street photography&lt;/h3&gt;
&lt;p&gt;Eric Anderson is a photographer and web designer with a particularly great &lt;a href=&quot;https://www.esquareda.com&quot; &gt;portfolio of street photography&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Use localStorage for Tab Synchronization</title><link>https://nabeelvalley.co.za/blog/2024/07-03/localstorage-based-sync.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/07-03/localstorage-based-sync.html</guid><description>Synchronize data between browser tabs using localStorage</description><pubDate>Thu, 07 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Use localStorage for Tab Synchronization&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;localStorage&lt;/h2&gt;
&lt;p&gt;localStorage is a method for persistent data storage in the browser. The storage itself is a simple key-value store with a synchronous API&lt;/p&gt;
&lt;p&gt;We can write data to a given key using the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-key&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-data&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can get that data back using:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; myData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;my-key&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Pretty neat right?&lt;/p&gt;
&lt;p&gt;For the purpose of this post we&amp;#39;ll look into how we can use this as a method for sending data between different browser tabs of the same website&lt;/p&gt;
&lt;h2&gt;Storage Event&lt;/h2&gt;
&lt;p&gt;Aside from just data storage - localStorage (as well as sessionStorage) provides us with a notification when the data in a storage is changed - this is called a &lt;code&gt;StorageEvent&lt;/code&gt;. What&amp;#39;s particularly interesting to us is that it&amp;#39;s fired in all other tabs of a particular site when any a tab of that site modifies the data&lt;/p&gt;
&lt;p&gt;We can listen for this event using &lt;code&gt;window.addEventListener&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;window.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;storage&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Something has changed in storage&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, if you think about it for a short while, you may come to an interesting conclusion - we can talk to other tabs&lt;/p&gt;
&lt;h2&gt;Speaking to Tabs&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Open this page in two different windows side-by-side for this example&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since we can talk between tabs, we can synchronize parts of our UI using the messages we recieive&lt;/p&gt;
&lt;p&gt;Below we have a button that uses this - each time it is pressed in one tab - it updates the count in all tabs&lt;/p&gt;
&lt;p&gt;&lt;site-snippet-preview&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;localstorage-sync/SynchronizedButton.html&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;sync-button&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Count&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; button&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;sync-button&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; syncKey&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;button-example-key&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getCount&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(syncKey) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;0&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseInt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(count)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; render&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getCount&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      button.innerText &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `Count: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    window.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;storage&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    button.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getCount&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nextCount&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // Since the storage event only fires in other tabs we must also render our own tab&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(syncKey, nextCount.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;div&gt;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;button id=&quot;sync-button&quot; &gt;Count&lt;/button&gt;

&lt;script&gt;
  (function () {
    const button = document.getElementById(&#39;sync-button&#39;)
    const syncKey = &#39;button-example-key&#39;

    const getCount = () =&gt; {
      const count = window.localStorage.getItem(syncKey) || &#39;0&#39;

      return parseInt(count)
    }

    const render = () =&gt; {
      const count = getCount()
      button.innerText = `Count: ${count}`
    }

    window.addEventListener(&#39;storage&#39;, () =&gt; render())

    button.addEventListener(&#39;click&#39;, () =&gt; {
      const count = getCount()
      const nextCount = count + 1

      // Since the storage event only fires in other tabs we must also render our own tab
      render()
      window.localStorage.setItem(syncKey, nextCount.toString())
    })

    render()
  })()
&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;&lt;/div&gt;&lt;/site-snippet-preview&gt;&lt;/p&gt;
&lt;h2&gt;Generic Implementation&lt;/h2&gt;
&lt;p&gt;So overall, this is a pretty neat method for sharing data between pages, but we end up having to do some repetitive work when setting this up in many places or when working with anything that isn&amp;#39;t a string (as you can see with the &lt;code&gt;parseInt&lt;/code&gt;s required in the above example)&lt;/p&gt;
&lt;p&gt;To make this a little more generic we&amp;#39;re first going to extract the getting and setting of data into their own functions:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;initial&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; existing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;existing) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; initial&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(existing) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; initial&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;These provide relatively simple wrappers around the reading and writing of data and making it possible for us to work with objects&lt;/p&gt;
&lt;p&gt;Next, we can provide an easy way to define a data reader and writer - the reason we define these separately is to make the interface a little easier for consumers to use without needing to rearrange all their code:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SetValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createSyncReader&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  initial&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  onChange&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  window.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;storage&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, initial)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    onChange&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, initial)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; createSyncWriter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; SetValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    setValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Our reader function will call the provided &lt;code&gt;onChange&lt;/code&gt; callback that is provided to it when the data is changed with the parsed data. We can implement the same button as above using this new code as can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;site-snippet-preview&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;localstorage-sync/SynchronizedButtonRefactor.html&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;sync-button-refactor&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Count&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;button&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;initial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; existing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;existing) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;          return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; initial;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(existing);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (_a) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; initial;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window.localStorage.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setItem&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createSyncReader&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;initial&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;onChange&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      window.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;storage&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, initial);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        onChange&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, initial);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createSyncWriter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(key, value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; button&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;sync-button-refactor&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; syncKey&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;button-example-key-refactor&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; render&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      button.innerText &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `Count: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;count&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; readValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createSyncReader&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(syncKey, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, render);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; writeValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createSyncWriter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(syncKey);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    button.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;click&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; count&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; readValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nextCount&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // Since the storage event only fires in other tabs we must also render our own tab&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(nextCount);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      writeValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(nextCount);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;readValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;div&gt;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;button id=&quot;sync-button-refactor&quot; &gt;Count&lt;/button&gt;

&lt;script&gt;
  (function () {
    const getValue = (key, initial) =&gt; {
      try {
        const existing = window.localStorage.getItem(key);
        if (!existing) {
          return initial;
        }
        return JSON.parse(existing);
      }
      catch (_a) {
        return initial;
      }
    };
    const setValue = (key, value) =&gt; window.localStorage.setItem(key, JSON.stringify(value));

    const createSyncReader = (key, initial, onChange) =&gt; {
      window.addEventListener(&quot;storage&quot;, () =&gt; {
        const value = getValue(key, initial);
        onChange(value);
      });
      return () =&gt; getValue(key, initial);
    };

    const createSyncWriter = (key) =&gt; (value) =&gt; setValue(key, value);

    const button = document.getElementById(&#39;sync-button-refactor&#39;);
    const syncKey = &#39;button-example-key-refactor&#39;;
    const render = (count) =&gt; {
      button.innerText = `Count: ${count}`;
    };
    const readValue = createSyncReader(syncKey, 0, render);
    const writeValue = createSyncWriter(syncKey);
    button.addEventListener(&#39;click&#39;, () =&gt; {
      const count = readValue();
      const nextCount = count + 1;
      // Since the storage event only fires in other tabs we must also render our own tab
      render(nextCount);
      writeValue(nextCount);
    });
    render(readValue());
  })()
&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;&lt;/div&gt;&lt;/site-snippet-preview&gt;&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage&quot; &gt;MDN localStorage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event&quot; &gt;MDN storage event&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 36, year 2024 - pretty printing</title><link>https://nabeelvalley.co.za/blog/2024/08-09/week-36-pretty-printing.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/08-09/week-36-pretty-printing.html</guid><pubDate>Sun, 08 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 36, year 2024 - pretty printing&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;this week has been a little insane so i&amp;#39;m actually amazed i&amp;#39;ve found 5 mins to put this together&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;p&gt;spent some time playing around with two little projects, one of which are pretty useful and the other is somewhat conceptual&lt;/p&gt;
&lt;h3&gt;delta&lt;/h3&gt;
&lt;p&gt;this is a &lt;a href=&quot;https://github.com/dandavison/delta&quot; &gt;cli tool for better git diffs&lt;/a&gt; and provides syntax highlighting for your git diff and some git commands. it&amp;#39;s also written in rust if you care about that sort of thing&lt;/p&gt;
&lt;h3&gt;fancy fonts&lt;/h3&gt;
&lt;p&gt;i also came across a &lt;a href=&quot;https://kuanwh.com/markdown-font/&quot; &gt;font which renders markdown as rich text&lt;/a&gt; using some fancy font features. it&amp;#39;s a little glitchy but really cool that this works without any JS&lt;/p&gt;
&lt;p&gt;additionally, there&amp;#39;s also &lt;a href=&quot;https://blog.glyphdrawing.club/font-with-built-in-syntax-highlighting/&quot; &gt;this font which does syntax highlighting&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;overall, fonts are getting pretty cool these days. &lt;a href=&quot;https://developer.chrome.com/blog/colrv1-fonts&quot; &gt;the chrome devblog has a cool bit about colrv1 fonts&lt;/a&gt; which let us do some pretty fancy things too&lt;/p&gt;
&lt;p&gt;it&amp;#39;s also worth taking at &lt;a href=&quot;https://x.com/JohannesMutter/status/1824948096205459903&quot; &gt;this thread&lt;/a&gt; which has some links to font related stuff worth checking out&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 32, year 2024 - branded types, nodes, and image segmentation</title><link>https://nabeelvalley.co.za/blog/2024/10-08/week-32-branded-types-nodes-and-image-segmentation.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/10-08/week-32-branded-types-nodes-and-image-segmentation.html</guid><pubDate>Sat, 10 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 32, year 2024 - branded types, nodes, and image segmentation&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;what i&amp;#39;m working on&lt;/h2&gt;
&lt;p&gt;i&amp;#39;ve still been spending a decent amount of time on my photo editing app and progress has been good. this week i put together a basic concept of how i want the ui to work as well as how i can translate configuration from the webGPU backend i&amp;#39;m using to the ui&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;react-flow&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;react-flow&lt;/code&gt; is a library for building node-based user interfaces and has been pretty great to play around with and pretty much does what it says on the box&lt;/p&gt;
&lt;h2&gt;branded types&lt;/h2&gt;
&lt;p&gt;branded types are a way to bring some ideas around primitive types from functional languages to typescript. i find them to be a generally useful thing to know. i think they play very well with the concept of type-first design, as far as it goes &lt;a href=&quot;https://fsharpforfunandprofit.com/series/designing-with-types/&quot; &gt;this post by Scott Wlaschin&lt;/a&gt; is always something i recommend. as far as doing this in typescript i think &lt;a href=&quot;https://x.com/mattpocockuk/status/1625173884885401600?lang=en&quot; &gt;this thread by matt pocock&lt;/a&gt; is a pretty good reference as well as &lt;a href=&quot;https://typescript.tv/best-practices/improve-your-type-safety-with-branded-types/&quot; &gt;this post on typescript.tv&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;image segmentation&lt;/h2&gt;
&lt;p&gt;i came across the &lt;a href=&quot;https://ai.meta.com/blog/segment-anything-foundation-model-image-segmentation/&quot; &gt;segment anything model by meta&lt;/a&gt; which is a pretty cool model for image segmentation and is just generally fun to play around with&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Javascript Proxy Object</title><link>https://nabeelvalley.co.za/blog/2024/11-12/proxy-objects.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/11-12/proxy-objects.html</guid><description>Basic introduction to proxies in Javascript/Typescript</description><pubDate>Wed, 11 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Javascript Proxy Object&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Proxies allow us to wrap existing object and modify the behavior when interacting with them in some interesting ways. This post will take a look at a few things we can use them for&lt;/p&gt;
&lt;h2&gt;Something to work with&lt;/h2&gt;
&lt;p&gt;For the sake of this example we&amp;#39;ll be using Typescript. Let&amp;#39;s create a reference object type that we will interact with - we&amp;#39;re going to call this &lt;code&gt;MyApi&lt;/code&gt; and it&amp;#39;s defined simply as an object with a few methods on it:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Adds 2 numbers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@returns&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the result of addition&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  add&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Difference between 2 numbers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@returns&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; the result of subtraction&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  subtract&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * (secretly does some illegal stuff)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  illegal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Initial implementation&lt;/h2&gt;
&lt;p&gt;We can implement a simple object that satisifies this APi as below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; baseApi&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyApi&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  add&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; a &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  subtract&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; a &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  illegal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; a &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Log accesses&lt;/h2&gt;
&lt;p&gt;For this example we&amp;#39;ll consider the &lt;code&gt;illegal&lt;/code&gt; method as special. We&amp;#39;ll want to track each time the &lt;code&gt;illegal&lt;/code&gt; property is accessed. Using a &lt;code&gt;Proxy&lt;/code&gt; we can wrap the &lt;code&gt;baseApi&lt;/code&gt; and provide a &lt;code&gt;get&lt;/code&gt; method that will handle property access and allow us to see what property of our object is being accessed&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;illegal&lt;/code&gt; is accessed, we log out a message:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; logAccess&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Proxy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(baseApi, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;target&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (key &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;illegal&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Tried to access illegal method&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // return the property from the original object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; target[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;logAccess.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;illegal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// logs out the message before calling the function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Prevent illegal access&lt;/h2&gt;
&lt;p&gt;We can also do stuff like create a type of &lt;code&gt;WithoutIllegal&lt;/code&gt; version of &lt;code&gt;MyApi&lt;/code&gt; in which we remove the property from the type definition. Additionally, we can also make this throw an error if someone attempts to access it at runtime as can be seen below. This is very similar to the previous example but now we have a direct impact on the consumer&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WithoutIllegal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Omit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;illegal&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; police&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Proxy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;WithoutIllegal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;(baseApi, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;target&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (key &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;illegal&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;accessing illegal properties is a crime&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; target[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;try&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // @ts-expect-error this is now an error since we say &amp;quot;illegal is not defined&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  police.illegal;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // @ts-expect-error if we try to access it, it will throw&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  police.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;illegal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;} &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;catch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Got illegal access&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, err);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Interact with other objects&lt;/h2&gt;
&lt;p&gt;During the proxying process, we can also do things like interact with objects that aren&amp;#39;t defined within our base object itself:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; logs&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[][] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; withLogs&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Proxy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(baseApi, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;target&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyApi&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; method&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; target[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;b&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      logs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;accessing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, key, a, b]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; method&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a, b);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      logs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;result&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, result]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;withLogs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;add&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;withLogs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;subtract&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;withLogs.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;illegal&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(logs);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessing&amp;#39;, &amp;#39;add&amp;#39;, 1, 2 ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;result&amp;#39;, 3 ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessing&amp;#39;, &amp;#39;subtract&amp;#39;, 1, 2 ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;result&amp;#39;, -1 ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessing&amp;#39;, &amp;#39;illegal&amp;#39;, 1, 2 ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;result&amp;#39;, 0.5 ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Creating fake objects&lt;/h2&gt;
&lt;p&gt;We can also create an object in which &lt;em&gt;any&lt;/em&gt; properties can exist and have a specific value, for example an object that has this structure for any key given:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    myKey&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;myKey&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This can be done like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; fake&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Proxy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;target&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;property&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        [property]: property,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(fake);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(fake.name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// { name: &amp;#39;name&amp;#39; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(fake.age);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// { age: &amp;#39;age&amp;#39; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(fake.somethingelse);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// { somethingelse: &amp;#39;somethingelse&amp;#39; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;It&amp;#39;s also interesting to note that the &lt;code&gt;fake&lt;/code&gt; object has no direct properties, and we cxan see that when we log it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Recursive proxies&lt;/h2&gt;
&lt;p&gt;Proxies can also return other proxies. This allows us to proxy objects recursively. For example, given the following object:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; deepObject&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  a: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    b: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      getC&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        c&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;x&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;y&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          answer: x &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; y,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can create a proxy that tracks different actions, such as property acccess. Recursive proxies can be created by returning a new proxy at the levels that we care about. In the below example, we create a proxy for every property that we access as well as for the result of every function call:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tracker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[][] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createTracker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; object&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;obj&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;prefix&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Proxy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(obj, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    apply&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;target&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;thisArg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;argArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      tracker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;call&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, prefix, argArray]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; bound&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (target &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;args&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;bind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(thisArg);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; bound&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;argArray);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      tracker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;return&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, prefix, result]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;undefined&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // create a new proxy around the object that&amp;#39;s returned from a function call&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createTracker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result, prefix);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;_&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;prop&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;prefix&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}/${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;prop&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      tracker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;accessed&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, path]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nxt&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; obj[prop];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nxt &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;undefined&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nxt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // create a new proxy around the object that&amp;#39;s being accessed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createTracker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(nxt &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; object&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, path);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tracked&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createTracker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(deepObject);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tracked.a.b.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getC&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;c&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ result });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// { result: { answer: 3 } }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tracker);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessed&amp;#39;, &amp;#39;/a&amp;#39; ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessed&amp;#39;, &amp;#39;/a/b&amp;#39; ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessed&amp;#39;, &amp;#39;/a/b/getC&amp;#39; ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;call&amp;#39;, &amp;#39;/a/b/getC&amp;#39;, [] ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;return&amp;#39;, &amp;#39;/a/b/getC&amp;#39;, { c: [Function: c] } ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;accessed&amp;#39;, &amp;#39;/a/b/getC/c&amp;#39; ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;call&amp;#39;, &amp;#39;/a/b/getC/c&amp;#39;, [ 1, 2 ] ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   [ &amp;#39;return&amp;#39;, &amp;#39;/a/b/getC/c&amp;#39;, { answer: 3 } ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy&quot; &gt;MDN Proxy Docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Passwords</title><link>https://nabeelvalley.co.za/blog/2024/12-04/passwords.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/12-04/passwords.html</guid><description>Some casual commentary</description><pubDate>Fri, 12 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Passwords&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Good design is actually a lot harder to notice than poor design, in part because good designs fit our needs so well that the design is invisible, serving us without drawing attention to itself. Bad design, on the other hand, screams out its inadequacies, making itself very noticeable.&amp;quot; - Don Norman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just had a silly experience. I needed to log into an app on my browser and had the following nonsensical series of steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to website&lt;/li&gt;
&lt;li&gt;Click &amp;quot;Login&amp;quot;&lt;/li&gt;
&lt;li&gt;Username automatically filled in by my password manager&lt;/li&gt;
&lt;li&gt;Click &amp;quot;Next&amp;quot;&lt;/li&gt;
&lt;li&gt;Password is automatically filled in by my password manager&lt;/li&gt;
&lt;li&gt;Click &amp;quot;Submit&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Maybe there&amp;#39;s trickiness I&amp;#39;m not seeing here but from my perspective it doesn&amp;#39;t look like I&amp;#39;m required in this flow?&lt;/p&gt;
&lt;p&gt;Between my browser and my password manager, and to some extent the application I&amp;#39;m logging into, this problem can be solved without my involvement. You have enough information to know who I am and log me in automatically when visiting a page - there&amp;#39;s no real reason I ever need to see a login page when using an application on my device/browser&lt;/p&gt;
&lt;p&gt;I&amp;#39;m thinking that since the data is already there at a hardware level this should be a solved problem&lt;/p&gt;
&lt;p&gt;Then again, maybe this is what &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API&quot; &gt;Web Authentication API&lt;/a&gt; is meant to solve but I&amp;#39;m not too sure, I think it&amp;#39;s still a click too many. That and my experiences with it have been a little inconsistent&lt;/p&gt;
&lt;p&gt;I think we&amp;#39;re still missing some unifying solution - some means of tying my identity to a set of devices once and having the friction removed at every other point&lt;/p&gt;
&lt;p&gt;Generally things get smoother as time goes but I feel that hasn&amp;#39;t been then case with auth. Every day there&amp;#39;s a new step - OTPs, &amp;quot;Magic Links&amp;quot; or &amp;quot;Your password can&amp;#39;t be the same as your past 5 passwords&amp;quot; which create a mess for most people. We like to think that most people just use password managers but that isn&amp;#39;t really the case. Many people struggle with this constantly&lt;/p&gt;
&lt;p&gt;I&amp;#39;m not sure what the solution is but I think we need to start thinking about security from a bit more of a human angle and less of a computer one&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>The Most Awkward Person in the Room</title><link>https://nabeelvalley.co.za/blog/2024/13-07/on-being-awkward.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/13-07/on-being-awkward.html</guid><description>The challenge of language</description><pubDate>Sat, 13 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;The Most Awkward Person in the Room&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;I should preface this by saying that I don&amp;#39;t think I&amp;#39;m particularly good at English&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&amp;#39;s already challenging enough trying to communicate in a foreign country - add in some loud music and a sketchy location and we&amp;#39;ve just made that about ten times more difficult&lt;/p&gt;
&lt;h2&gt;English, or something&lt;/h2&gt;
&lt;p&gt;A friend of mine mentioned to me the other day that they&amp;#39;ve been thinking about moving to the UK because of how much gets lost when communicating in a second language&lt;/p&gt;
&lt;p&gt;This morning I met up with some developers and we were chatting about software but also politics (since everything is politics) and a few times during the conversation the perfect sentence popped into my head - but I couldn&amp;#39;t say it. There was the immediate realization that the meaning would be lost, the nuance would not translate. &lt;/p&gt;
&lt;p&gt;I&amp;#39;ve been experiencing this a lot at work well, while everyone speaks English perfectly, there&amp;#39;s just a little bit of style that has to be eliminated to communicate clearly - something I don&amp;#39;t find myself doing when speaking to native English speakers. I simplify words, use fewer metaphors, and slow down significantly&lt;/p&gt;
&lt;p&gt;Anyways, I went home and spoke to my wife and she had some strong opinions about the churro place she went to. All the signs were in English but when she tried to order in English the person working there didn&amp;#39;t seem to understand what she was saying, even though he repeated all the same things back to her in English&lt;/p&gt;
&lt;p&gt;Now, if I&amp;#39;m being completely honest here, some of these problems exist when speaking through language boundaries but it&amp;#39;s a lot less frequent&lt;/p&gt;
&lt;h2&gt;The Curse of the Awkward&lt;/h2&gt;
&lt;p&gt;So, anyways - I&amp;#39;m not a super social person - I don&amp;#39;t really know how to speak to people and kind of overthink every interaction&lt;/p&gt;
&lt;p&gt;On one of the Photography groups I&amp;#39;m on someone posted an invite to a &amp;quot;Party&amp;quot; which was meant to just be a social event for photographers and creatives. They also added a tiny note saying &amp;quot;no alcohol event, more like networking&amp;quot;&lt;/p&gt;
&lt;p&gt;No alcohol you say? Do such things exist? Okay count me in - is what I would have said if I didn&amp;#39;t spend two hours contemplating whether or not this would be the worst experience of my life&lt;/p&gt;
&lt;p&gt;It was a bit in the middle of nowhere but looked like it wouldn&amp;#39;t take me too long to get there - so I was like yeah sure. I dropped them a message and said I&amp;#39;d meet them there - this wasn&amp;#39;t someone I&amp;#39;d met before but I know a few people who know them so I figured it should be alright&lt;/p&gt;
&lt;p&gt;I got to what Google told me was the destination but this was just a weird abandoned building with automatic doors that wouldn&amp;#39;t open automatically&lt;/p&gt;
&lt;p&gt;I saw a person with a camera standing in the passage upstairs and figured I was probably in the right place but had no idea what to expect&lt;/p&gt;
&lt;p&gt;The dude I was supposed to meet got there about 5 minutes after I did and we went in together (after awkwardly waiting for someone to see us and let us in)&lt;/p&gt;
&lt;p&gt;It was super weird. There were photographers everywhere and people posing all over the space, the music was maaad loud and there were some people live-DJing&lt;/p&gt;
&lt;p&gt;This was a kind of chaos I wasn&amp;#39;t ready for&lt;/p&gt;
&lt;p&gt;I think the worst part of going to a place you&amp;#39;ve never been is not knowing anyone - events are a sort of social fabric and it&amp;#39;s always a bit scary being a loose thread&lt;/p&gt;
&lt;p&gt;I floated about not too sure what to do, looking around, just trying to see what was happening - I was kind of shocked at how diverse the space was. It&amp;#39;s rare in the Netherlands to end up in a room where you aren&amp;#39;t the only person of colour in&lt;/p&gt;
&lt;p&gt;This is something I noticed the last time I attended a photography meetup which was that it was a lot less white than the professional spaces I tend to be involved in&lt;/p&gt;
&lt;p&gt;There may be some social commentary that could be added here but that&amp;#39;s not what this post is about so moving on&lt;/p&gt;
&lt;p&gt;Later in the evening there was a short poetry performance which was cool - but that&amp;#39;s about all I can say about it - the poetry was in Dutch and while I think my rudimentary understanding of the language was enough to grasp the high level idea of it, I feel like a lot of meaning and intent was lost in translation&lt;/p&gt;
&lt;h2&gt;Thought&lt;/h2&gt;
&lt;p&gt;I think the way we communicate with people close to us resonates on a level that&amp;#39;s more than just the words we&amp;#39;re saying. There&amp;#39;s an understanding that becomes so difficult to interpret when speaking a second language&lt;/p&gt;
&lt;p&gt;Maybe there&amp;#39;s something I&amp;#39;m missing here, maybe there&amp;#39;s something to be had where language isn&amp;#39;t the main factor - where the words we say aren&amp;#39;t the foundation of our relationships. But maybe that&amp;#39;s a thought for another day&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>More generic than it should be</title><link>https://nabeelvalley.co.za/blog/2024/15-08/handling-complex-typescript-generics.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/15-08/handling-complex-typescript-generics.html</guid><description>A method for designing highly generic APIs in Typescript</description><pubDate>Thu, 15 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;More generic than it should be&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;A method for designing highly generic APIs in Typescript&lt;/p&gt;
&lt;h2&gt;The Pattern&lt;/h2&gt;
&lt;p&gt;A recurring point I&amp;#39;ve seen when designing highly generic API&amp;#39;s in Typescript is around giving consumers of an API an interface that requires the least amount of extra information from them. For example, take the function below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  age&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProp&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above example, we define a function called &lt;code&gt;getProperty&lt;/code&gt; that gets the &lt;code&gt;key&lt;/code&gt; property of &lt;code&gt;data&lt;/code&gt;, we would use this like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The problem here is that the user of this function has to provide both generics when using the function since the object with type &lt;code&gt;D&lt;/code&gt; is only provided to the function that is returned. The experience of a consumer here is a little cumbersome and would be nicer if we didn&amp;#39;t have to do this.&lt;/p&gt;
&lt;h2&gt;Some Other Ideas&lt;/h2&gt;
&lt;p&gt;We can also try the following where we just provide the &lt;code&gt;name&lt;/code&gt;, but this won&amp;#39;t work:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;); &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Error: Argument of type &amp;#39;string&amp;#39; is not assignable to parameter of type `never`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is because the function doesn&amp;#39;t know what type it&amp;#39;s dealing with. The obvious next thing we can try is just provide a single type argument, but this doesn&amp;#39;t work either since typescript needs us to provide both generics since we&amp;#39;re not defaulting the second one&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;); &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Error: Expected 2 type arguments, but got 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; default the type of &lt;code&gt;K&lt;/code&gt; which would take away our error but would also completely remove the benefit of it being a generic parameter in this case which is to narrow down the type the function returns&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, a general strategy here is to instead swap around our type arguments, what if we defined &lt;code&gt;getProperty&lt;/code&gt; instead by defining &lt;code&gt;D&lt;/code&gt; in terms of &lt;code&gt;K&lt;/code&gt;, something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProp&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;D&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, this works and may be okay for your usecase, but often we want to constrain the &lt;code&gt;getProperty&lt;/code&gt; function with the type of data known in advance. Also it can be more complicated than just a record with the key of the input type and this isn&amp;#39;t always something we can extend more generally&lt;/p&gt;
&lt;p&gt;This also has the issue that when using the &lt;code&gt;getProperty&lt;/code&gt; function we end up with a function that lets anything through that maybe has a &lt;code&gt;name&lt;/code&gt; property which may not be what we want&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;); &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// getter is not constrained by the type of `D`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;A Weird Solution&lt;/h2&gt;
&lt;p&gt;What can be a better solution is to split our function into a part that provides a generic and a part that provides data:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createGetter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This can now be used in a way where we don&amp;#39;t specify any more generics than we need and has the weirdness of us invoking a function twice for no reason other than providing a generic&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createGetter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can also make this a bit easier on the eyes by creating an intermediate variable:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dataGetter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createGetter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; dataGetter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This isn&amp;#39;t too bad, and I&amp;#39;d be okay to leave it here, but after speaking to some other developers I end up having a lot of questions around how the mechanics of the generic type need to work as well as the fact that we have multiple levels of functions returning functions that creates confusion when trying to use this code&lt;/p&gt;
&lt;h2&gt;A Classier Way&lt;/h2&gt;
&lt;p&gt;Weirdly, thinking of this as a class seemed to help. Instead of using a function to preload a generic, we can use a class:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Getter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  property&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; keyof&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; D&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;K&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data[key];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;I think this code reads a bit nicer and it&amp;#39;s clear where the different generics come from. Ultimately it&amp;#39;s doing the exact same thing but we&amp;#39;re hiding the complexity of initializing the generic behind some syntax&lt;/p&gt;
&lt;p&gt;Using this is quite nice now as well:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dataGetter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Getter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; getName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dataGetter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;property&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;What&amp;#39;s also different with using the class approach is that things have names now, we know that we are calling the &lt;code&gt;.property&lt;/code&gt; method which is giving us something to work with. Something about using classes gives people a bit more familiarity when working with generic things and creates a good relationship between the mechanics of the method and the mental model most developers have of class based development&lt;/p&gt;
&lt;h3&gt;Gross&lt;/h3&gt;
&lt;p&gt;I&amp;#39;m more and more moving towards the idea that this kind of generic stuff should be kept to a minimum. This is a relatively simple example but these concepts can get pretty complex and perhaps speaks to something more fundementally incorrect about the data structures being worked with. If you can control the data structures, then ideally simplify them so you don&amp;#39;t need this level of type magic, but if you do - it&amp;#39;s always handy to have a way to express things that makes it easier for other developers to understand and work with&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 37, year 2024 - ui paradigms and comic books</title><link>https://nabeelvalley.co.za/blog/2024/15-09/week-37-ui-paradigms-and-comic-books.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/15-09/week-37-ui-paradigms-and-comic-books.html</guid><pubDate>Sun, 15 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 37, year 2024 - ui paradigms and comic books&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;between doomscrolling and visiting &lt;a href=&quot;https://www.foam.org/?gad_source=1&amp;amp;gclid=Cj0KCQjwi5q3BhCiARIsAJCfuZkTCodlHCRjT5oZANFRotVr8C131p7Ad5DIjty3-1DrBP9PqkiXSPcaAkJmEALw_wcB&quot; &gt;FOAM&lt;/a&gt; there was barely any time to put something together but here we go&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;p&gt;i spent a decent amount of time comparing different ways of doing the same things. recently i&amp;#39;ve been thinking about ui state management, but first - some art&lt;/p&gt;
&lt;h3&gt;mœbius&lt;/h3&gt;
&lt;p&gt;mœbius is the pseudonym of &lt;a href=&quot;https://en.wikipedia.org/wiki/Jean_Giraud&quot; &gt;Jean Henri Gaston Giraud&lt;/a&gt; who was a french cartoonist. i&amp;#39;ve found &lt;a href=&quot;https://www.iamag.co/the-art-of-moebius/&quot; &gt;his work&lt;/a&gt; fascinating for quite some time. the level of detail packed into each frame is astonishing&lt;/p&gt;
&lt;h3&gt;state management&lt;/h3&gt;
&lt;p&gt;ui state is always something where there are an infinite number of solutions, each with their own drawbacks or drawfronts (of course that&amp;#39;s the opposite right?)&lt;/p&gt;
&lt;h4&gt;reactive programming&lt;/h4&gt;
&lt;p&gt;something old to get us started. i think reactive programming (using things like RxJS or hand-rolled equivalents) give us a good starting point for managing state and &lt;a href=&quot;https://gist.github.com/staltz/868e7e9bc2a7b8c1f754&quot; &gt;this gist by André Staltz&lt;/a&gt; looks like a nice intro to the topic&lt;/p&gt;
&lt;h4&gt;signals&lt;/h4&gt;
&lt;p&gt;i came across a library called &lt;a href=&quot;https://github.com/adamhaile/S&quot; &gt;S.js&lt;/a&gt; which is one of the earlier signal implementations around and works with a jsx based framework called &lt;a href=&quot;https://github.com/adamhaile/surplus&quot; &gt;surplus&lt;/a&gt;. both of which are made by Adam Haile and last updated about 6 years ago (so probably don&amp;#39;t pitch this during standup on monday)&lt;/p&gt;
&lt;p&gt;if you&amp;#39;re looking for a more modern implementation of signals, your favourite framework probably has something: &lt;a href=&quot;https://angular.dev/guide/signals&quot; &gt;angular&lt;/a&gt; - and &lt;a href=&quot;https://github.com/preactjs/signals&quot; &gt;a bunch of other stuff&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;state machines&lt;/h4&gt;
&lt;p&gt;when talking about state management i always like to put &lt;a href=&quot;https://xstate.js.org/&quot; &gt;xstate&lt;/a&gt; on the table since it&amp;#39;s a really handy library with some great developer experience and tooling built in. &lt;a href=&quot;https://nabeelvalley.co.za/blog/2023/31-01/xstate-draggable-div/&quot; &gt;i wrote a little intro&lt;/a&gt; a while back if you&amp;#39;d like to get a feel for the library as well&lt;/p&gt;
&lt;h4&gt;strictness&lt;/h4&gt;
&lt;p&gt;something more obscure. i find the approach of &lt;a href=&quot;https://elm-lang.org/&quot; &gt;elm&lt;/a&gt; for ui quite interesting and is outlined in &lt;a href=&quot;https://guide.elm-lang.org/architecture/&quot; &gt;the elm architecture&lt;/a&gt;. i first came across it in &lt;a href=&quot;https://zaid-ajaj.github.io/the-elmish-book/#/&quot; &gt;the elmish book&lt;/a&gt; which presents this method for building interfaces using &lt;a href=&quot;https://fsharp.org/&quot; &gt;f#&lt;/a&gt; and &lt;a href=&quot;https://fable.io/&quot; &gt;fable&lt;/a&gt; which is compiler that turns f## into javascript.&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Parameters, but only sometimes</title><link>https://nabeelvalley.co.za/blog/2024/16-08/optional-parameters-and-overloads-in-typescript.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/16-08/optional-parameters-and-overloads-in-typescript.html</guid><description>Better handling of function generics with optional parameters in Typescript using overloads</description><pubDate>Fri, 16 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Parameters, but only sometimes&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Ran into this question today and I thought it would be a nice little example to document:&lt;/p&gt;
&lt;p&gt;I have the following function &lt;code&gt;doWork&lt;/code&gt; that is generic:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This function can be called in any of the following ways:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Works&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//  T is string, data is string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// T is undefined, data is undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// T is undefined, data is undefined;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// T is string, data is undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above usage, we want to make it so that users of this function need to provide the &lt;code&gt;data&lt;/code&gt; parameter when calling the function when the type is provided. Now, a simple solution could be to define our function as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The problem is that it&amp;#39;s a bit ugly for cases where we want to allow &lt;code&gt;T&lt;/code&gt; as &lt;code&gt;undefined&lt;/code&gt;, because you now have to do this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So the issue here is that we only want to make the &lt;code&gt;data&lt;/code&gt; parameter required when &lt;code&gt;T&lt;/code&gt; is not &lt;code&gt;undefined&lt;/code&gt;, there&amp;#39;s a lot of funny stuff you can try using generics and other weird typescript notation, but simply defining the necessary overloads for our method works:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * This specifically handles the case where T is undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * The data param will be required since T is not undefined here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * This provideds an implementation that is the same as before while providing a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * better interface for function users&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, having defined those function overloads, we can use the function and it works as expected:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Works&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//  T is string, data is required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// T is undefined, data parameter is not required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// T is undefined, specifying data is still okay&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Error: Type &amp;#39;string&amp;#39; does not satisfy the constraint &amp;#39;undefined&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// this overload is not valid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The added benefit of this method is that we can also write the doc comments for each implementation separately which can be a nice way for us to give additional context to consumers. It&amp;#39;s kind of like having two specialized functions without the overhead of having to implement them independently&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 33, year 2024 - compilers, videography and good intentions</title><link>https://nabeelvalley.co.za/blog/2024/17-08/week-33-compilers-videography-and-good-intentions.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/17-08/week-33-compilers-videography-and-good-intentions.html</guid><pubDate>Sat, 17 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 33, year 2024 - compilers, videography and good intentions&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;what i&amp;#39;m working on&lt;/h2&gt;
&lt;p&gt;this week i spent some time writing a small compiler to take my node based ui and compile it into a web gpu shader that i can then render images with - and ... that works now. i&amp;#39;m currently in the process of creating a solution for passing user input data between the ui and the gpu which shouldn&amp;#39;t be too difficult - that&amp;#39;s pretty much the last thing i need to do before i can have something that i can actually edit some photos with&lt;/p&gt;
&lt;p&gt;additionally, i spent far too much time fighting with typescript and wrote a bit about &lt;a href=&quot;https://nabeelvalley.co.za/blog/2024/16-08/optional-parameters-and-overloads-in-typescript/&quot; &gt;generic function overloads&lt;/a&gt; and &lt;a href=&quot;https://nabeelvalley.co.za/blog/2024/15-08/handling-complex-typescript-generics/&quot; &gt;even more generic functions&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;h3&gt;crafting interpreters&lt;/h3&gt;
&lt;p&gt;i&amp;#39;ve been reading &lt;a href=&quot;https://craftinginterpreters.com/&quot; &gt;crafting interpreters by Robert Nystrom&lt;/a&gt; which takes you through the entire process of implementing an interpreter for a custom programming language&lt;/p&gt;
&lt;h3&gt;the art of showing up&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=UJzh8X4Z8ys&quot; &gt;this vlog by Life of Riza&lt;/a&gt; is a little story about just being present, it&amp;#39;s a really uplifting watch and just an exciting little journey overall&lt;/p&gt;
&lt;h3&gt;a phoneless summer&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=7kseFWPllIo&quot; &gt;a &amp;quot;TVlog&amp;quot; by Anna Maria Luisa&lt;/a&gt; dealing with the awareness of time passing. excellent vibes and great writing&lt;/p&gt;
&lt;h3&gt;then next comes&lt;/h3&gt;
&lt;p&gt;if you share my internet you may have seen &lt;a href=&quot;https://www.youtube.com/watch?v=o1OsDWT_DUc&quot; &gt;exurb1a&amp;#39;s latest existential crisis&lt;/a&gt; which starts off as a look into a potential future of humanity until it takes us full circle into wishing we had any idea what anything is at all&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;and thanks for reading, till next week!&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>On Falling Down</title><link>https://nabeelvalley.co.za/blog/2024/19-04/falling.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/19-04/falling.html</guid><description>Responding to change</description><pubDate>Fri, 19 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;On Falling Down&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Today was kinda shitty. Actually really shitty.&lt;/p&gt;
&lt;p&gt;But also &lt;/p&gt;
&lt;p&gt;maybe not&lt;/p&gt;
&lt;p&gt;Its always weird sitting down to write about what&amp;#39;s going on in your head. I&amp;#39;m currently in a train at night hoping I&amp;#39;ll make it home in the next two hours&lt;/p&gt;
&lt;p&gt;Today was a bit insane. I has to shuffle between trains and go to places I&amp;#39;ve never been. Had to go through a storm feeling like I was constantly about to get thrown into a river by winds far stronger than they had any right to be&lt;/p&gt;
&lt;p&gt;Well. I guess that&amp;#39;s as good a place as any to start&lt;/p&gt;
&lt;p&gt;So, we had a little ski trip planned for work to this weird indoor ski slope in the middle of nowhere. The journey there was gonna be long but was straightforward enough - take two trains and two buses then walk for 8 minutes&lt;/p&gt;
&lt;p&gt;That was not how it went&lt;/p&gt;
&lt;p&gt;So, I got onto the first train - the one I usually take to get to the Utrecht Central station, that was a little busy but nothing too unusual for 4pm on a Friday. When I got to the station I had to catch another train - this one to The Hague - and this is when everything descended into chaos&lt;/p&gt;
&lt;p&gt;The train to The Hague was cancelled - but I was already on it - it was going to Leiden, no further - oh, and pretty much any train going anywhere past Leiden was also cancelled&lt;/p&gt;
&lt;p&gt;Oh, and there isn&amp;#39;t really any app that does &amp;quot;Hi, I&amp;#39;m already on this train but I need to go to this other place, where do I get off?&amp;quot; (Like seriously, this needs to exist)&lt;/p&gt;
&lt;p&gt;After going insane for a while, I resigned myself to my fate, put on some headphones - oh, did I mention that mine were dead so I borrowed my wifes? - and put on a good playlist (after briefly attempting to listen to Taylor Swift&amp;#39;s newest album). It&amp;#39;s kind of weird how much calm the right playlist can bring&lt;/p&gt;
&lt;p&gt;But anyways, It looks like there are some buses I can use from Leiden sort of - so let&amp;#39;s do that&lt;/p&gt;
&lt;p&gt;Now the thing is - since all the trains were stopping in Leiden - the station was absolutely packed. All i could see was a sea of heads&lt;/p&gt;
&lt;p&gt;(one moment, i need to switch trains)&lt;/p&gt;
&lt;p&gt;So, by the skin of my teeth i managed to get into a bus that was heading in the direction i needed to go. It was full, there were some loud americans, and some teenagers talking about tik tok songs, we drove past lots of sheep&lt;/p&gt;
&lt;p&gt;Oh, the bus was also 7 minutes late because of the mess at the station - I wasn&amp;#39;t gonna make the next swap - I had to figure out which stop to take &lt;/p&gt;
&lt;p&gt;My options were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get off at some rando bus stop and walk for 20 minutes&lt;/li&gt;
&lt;li&gt;Get off at some other rando bus stop to wait about an hour and then walk for 10 minutes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Eventually I made it to a bus stop in the middle of nowhere&lt;/p&gt;
&lt;p&gt;I took option 1 - maybe it&amp;#39;s me, maybe i&amp;#39;m the problem - but, just after I got off the bus and oriented my google maps and got my camera out to enjoy my stroll and maybe take some pictures of some lil sheeps - the mother of all storms descended upon lil ol me.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t know what happened, but the light drizzle turned into a beast with winds trying to steal my phone and camera and a torrent of rain racing to drown me&lt;/p&gt;
&lt;p&gt;Another test of my sanity today. I can&amp;#39;t control the weather I suppose, not any more than I can control bus schedules I guess&lt;/p&gt;
&lt;p&gt;So I walked, slowly, taking pictures of everything I thought was interesting&lt;/p&gt;
&lt;p&gt;Yes, the sheep. And also the little yellow flowers, and the weird giant metal alien space ship thing in the distance, and the poor post person trying their absolute hardest to make it to the next house on their little blue bicycle - the dutch really take their post seriously&lt;/p&gt;
&lt;p&gt;After about 10 minutes of walking I seemed to be in a forest, a hiking trail of some sort - I saw a parent and child riding their bicycle and a woman walking a dog - in this weather?? I can only conclude that the forest was haunted&lt;/p&gt;
&lt;p&gt;But eventually I figured out where my map was taking me - the weird alien thing - oh, that&amp;#39;s the ski slope&lt;/p&gt;
&lt;p&gt;With some end in sight, and a sense of where the heck I was, I walked now with a little more purpose&lt;/p&gt;
&lt;p&gt;I made it there eventually. Soaking wet, looking like whatever the thing that the cat dragged in would drag in&lt;/p&gt;
&lt;p&gt;Then, said hi to some work peeps and got some gear&lt;/p&gt;
&lt;p&gt;And so, may I present you with some snowboarding tips based on what some of my coworkers told me and what I learnt from falling a shit ton of times&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When trying to get on, dig your board in sideways with your back against the slope, this will keep you stable and help in trying to stand up, then commit when you stand - otherwise you&amp;#39;re just gonna spend the entire time on your butt&lt;/li&gt;
&lt;li&gt;Lean less than you think you need to and wait for the board to catch the snow&lt;/li&gt;
&lt;li&gt;While it&amp;#39;s a bit more difficult than the alternatives - take the weird lift thingy because you can keep your boots fully attached and once you get to the top you can just start snowboarding instead of doing the weird crab walk scoot struggle to standup thing&lt;/li&gt;
&lt;li&gt;You can always lean back more than you think and you probably won&amp;#39;t fall down - it&amp;#39;s a lot safer than learning forward and a really good way to quickly slow down if you&amp;#39;re bad at snowboarding&lt;/li&gt;
&lt;li&gt;When using the weird lift thingy just let it take you, don&amp;#39;t fight it - you will fall&lt;/li&gt;
&lt;li&gt;Fall. Yeah if you&amp;#39;re old like me it&amp;#39;s gonna suck tomorrow - but with every weird things on your feet sport, if you don&amp;#39;t get over the fear of falling you&amp;#39;re not really gonna get anywhere&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Oh and the new skiiers will get confused and stuck and not know how to standup - I don&amp;#39;t have a solution, this is just an observation - those things are a deathtrap&lt;/p&gt;
&lt;p&gt;(also snowboarding pants are cool, I kind of want some just to like wear as clothes)&lt;/p&gt;
&lt;p&gt;Also it&amp;#39;s cold and I&amp;#39;m waiting for my last train. This has been a really long day, but if this works out I&amp;#39;ll have at least managed to beat the plan all the map apps gave me - some consolation knowing you&amp;#39;re a bit smarter than some rando pathfinding algorithm i guess&lt;/p&gt;
&lt;p&gt;But anyways, what I think im trying to say is, it&amp;#39;s easy to get frustrated and angry when faced with challenges but all we can do is to make the best of what we can control and accept what we can&amp;#39;t.&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Life, Gleam, and Parser Combinators</title><link>https://nabeelvalley.co.za/blog/2024/20-07/parser-combinators-and-gleam.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/20-07/parser-combinators-and-gleam.html</guid><description>A short introduction to Parser Combinators</description><pubDate>Sat, 20 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Life, Gleam, and Parser Combinators&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Time&lt;/h2&gt;
&lt;p&gt;There&amp;#39;s never enough time to do the things we want to do. Recently I find myself struggling with this. There are too few hours in a day, too few days in a week. Between work and trying to simply stay alive there aren&amp;#39;t many hours left to do things you care about&lt;/p&gt;
&lt;p&gt;For the past year or so I&amp;#39;ve made a consistent effort to take my camera with me everywhere. It&amp;#39;s always either in my bag or in my hand. And I&amp;#39;ve taken a lot of pictures. The thing is, I feel that my photos have stagnated - they&amp;#39;re no better than they were a year ago, and arguably worse than five years ago. I seem to have hit some kind of local maximum, the point where I put just enough effort to passable but not nearly enough time to do anything useful&lt;/p&gt;
&lt;p&gt;As far as my photography goes, I&amp;#39;m planning to take fewer pictures, but spend a lot more time looking for ways to be better and create work that means more to me.&lt;/p&gt;
&lt;p&gt;The other area of my life that&amp;#39;s suffered due to poor time management is my technical learning. I&amp;#39;ve found programming to be an interesting lens through which to see the world, and different approaches and paradigms make that a constantly moving picture.&lt;/p&gt;
&lt;h2&gt;Gleam&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://gleam.run/&quot; &gt;Gleam&lt;/a&gt; is a functional programming language in the Erlang/Elixir ecosystem that compiles to code that can run on the Erlang VM and can also optionally target Javascript/Node&lt;/p&gt;
&lt;p&gt;There are a lot of things I still want to learn about and a lot of things I want to do. A few months ago I tried learning the Gleam but between windows being a generally disagreeable operating system and a general lack of direction I never quite got anywhere with it. Throught the documentation the language seemed like a nice little thing to learn and looked like a good balance of the strictness I wanted from a functional language and the ease of learning.&lt;/p&gt;
&lt;p&gt;Overall, I found it really easy to pick up Gleam - the syntax is very Javascripty and it&amp;#39;s got a very similar type system to F# both in terms of how the syntax looks as well as how it works overall. The standard library is also pretty good and covered most things I had to do and provided some utilities for a lot of common things as well as had testing configured from the get-go which made this overall quite a pleasure to setup&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve also been interested in Parser Combinators and spent some time learning about them from &lt;a href=&quot;https://www.youtube.com/playlist?list=PLP29wDx6QmW5yfO1LAgO8kU3aQEj8SIrU&quot; &gt;this YouTube Series by Low Byte Productions&lt;/a&gt; as well as as some work by &lt;a href=&quot;https://fsharpforfunandprofit.com/posts/understanding-parser-combinators/&quot; &gt;Scott Wlaschin on F# for Fun and Profit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The series by Low Byte was pretty great but was done in Javascript and didn&amp;#39;t really delve into some of the type complexities and behaviours that crop up when working with static types. It was on my second watch of Scott Wlaschin&amp;#39;s talk where the behaviour of generics really clicked and allowed me to related things back to Gleam&lt;/p&gt;
&lt;p&gt;As far as my actual experimentation goes I tried to use the kinds of parsers and combinators defined by the LowByte YouTube series while using the approach by Scott Wlaschin&lt;/p&gt;
&lt;p&gt;Overall I think I learnt quite a bit, I spent a lot of time looking at the Gleam code and rewriting things to work more consistely with the type of data structure I wanted. One of the things I found a little annoying things I found is that recursive functions seem to be definable only at the top-level of a module which adds some ceremony around doing things that involve recursion&lt;/p&gt;
&lt;p&gt;But anyways, all that aside, let&amp;#39;s take a look at some parser things&lt;/p&gt;
&lt;h2&gt;Parsers&lt;/h2&gt;
&lt;h3&gt;What is a Parser&lt;/h3&gt;
&lt;p&gt;In our context, a parser is simply a function that takes in some input, and tries to convert it into some meaningful pieces of data, further - a combinator is a function that takes one or more parsers and combines them into a new parser - get it? - combine = combinator.&lt;/p&gt;
&lt;p&gt;So in our context, we can define a type for a parser as a function that takes a &lt;code&gt;String&lt;/code&gt; and returns some result that tells use the part of the string which was matched and what was left over&lt;/p&gt;
&lt;p&gt;Additionally, a parser can be either successful or unsuccessful, and we do that using the &lt;code&gt;Result&lt;/code&gt; type that&amp;#39;s built into Gleam:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;matched: &lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;a, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;remaining: String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Err&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Result&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a), &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Err&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;A Simple Parser&lt;/h3&gt;
&lt;p&gt;We can also see that we are using this &lt;code&gt;a&lt;/code&gt; thing above, this is a generic type in Gleam. In our implementation we define that a parser just needs to return some kind of data as what was matched, but we don&amp;#39;t particularly care what that is&lt;/p&gt;
&lt;p&gt;For the sake of example, we can define a simple parser that matches a string exactly:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; starts_with_xx&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  case&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; string.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;starts_with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;xx&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    False&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Expected xx&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot; but found &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; input)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    True&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; remaining &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; string.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;drop_left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input, string.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;xx&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;xx&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, remaining))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Above, we define a parser called &lt;code&gt;starts_with_xx&lt;/code&gt; which will simply parse the characters &lt;code&gt;xx&lt;/code&gt; in a string. Now, overall this isn&amp;#39;t super useful and is pretty tedious if we need to do this each time we define a parser, so more generally we can define parsers using a function that takes some configuration and returns a parser&lt;/p&gt;
&lt;p&gt;So an example of a function that takes in a &lt;code&gt;String&lt;/code&gt; to match and returns a parser to us can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(start) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    case&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; string.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;starts_with&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input, start) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      False&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Expected &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot; but found &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;lt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; input)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      True&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; remaining &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; string.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;drop_left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input, string.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(start))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(start, remaining))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then redefine our above &lt;code&gt;starts_with_x&lt;/code&gt; parser in terms of this one, like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; starts_with_xx &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Running a parser we can see a bit about the type of data this returns:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parser &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;xxY&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Ok(ParserState(&amp;quot;xx&amp;quot;, &amp;quot;Y&amp;quot;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; error &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Yxx&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Error(&amp;quot;Expected xx but found Yxx&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can define other parsers using a similar style but this is the core of it, the above is very specifically a &lt;code&gt;Parser(String)&lt;/code&gt; but these can be more generic as we&amp;#39;ll see when we get to combinators&lt;/p&gt;
&lt;h3&gt;A Simple Combinator&lt;/h3&gt;
&lt;p&gt;Combinators are used to combine parsers in interesing ways. A simple combinator is the &lt;code&gt;left&lt;/code&gt; combinator which takes in two parsers and tries to parse them as a sequence, but will only keep the left-side of the parsed result.&lt;/p&gt;
&lt;p&gt;We can define this parser as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;l: Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a), &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;r: Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(b)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    case&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; l&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(okl) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        case&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; r&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(okl.remaining) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;          Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;          Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(okr) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(okl.matched, okr.remaining))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;It&amp;#39;s also interesting to note that we take a &lt;code&gt;Parser(a)&lt;/code&gt; and &lt;code&gt;Parser(b)&lt;/code&gt; but return a &lt;code&gt;Parser(a)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We can define a parser using the &lt;code&gt;choice&lt;/code&gt; combinator which would work as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parser &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; choice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;xyz&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Ok(ParserState(&amp;quot;x&amp;quot;, &amp;quot;z&amp;quot;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The parser above effectively throws away the second match in the choice but moves our inputs to the end of the second parser&lt;/p&gt;
&lt;p&gt;So far however we&amp;#39;re just working with strings, it would be nice to parse something more complex. In order to facilitate this we&amp;#39;re going to define a combinator called &lt;code&gt;map&lt;/code&gt; which will allow us to transform the result of the parser for the case where it succeeds (is &lt;code&gt;Ok&lt;/code&gt;)&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;parser: Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a), transform) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    case&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;      Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ok) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;transform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ok.matched), ok.remaining))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above definition you can see that the &lt;code&gt;parser&lt;/code&gt; is the first input to &lt;code&gt;map&lt;/code&gt;. We&amp;#39;re defining it like this because Gleam allows us to automatically pass the first argument as a result of a previous computation using the pipe operator which looks like &lt;code&gt;|&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To do something meaningful with &lt;code&gt;map&lt;/code&gt; we&amp;#39;re going to define a small type called &lt;code&gt;Token&lt;/code&gt; which will have a constructor called &lt;code&gt;TokenX&lt;/code&gt; which we will just use to represent us matching the character &lt;code&gt;X&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Token&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  TokenX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;matched: String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can then use the type we create along with the map operator to transform the result of the parsing to a more sophisticated data type:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parser &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TokenX&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;xyz&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Ok(ParserState(TokenX(&amp;quot;x&amp;quot;), &amp;quot;z&amp;quot;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So that&amp;#39;s pretty cool right?&lt;/p&gt;
&lt;h3&gt;A More Complex Parser&lt;/h3&gt;
&lt;p&gt;Using the basic idea of a parser and a combinator, we can define a whole bunch of them as I have &lt;a href=&quot;https://github.com/sftsrv/parz&quot; &gt;in my Parz project on GitHub&lt;/a&gt; we can compose them to create a parser for a more complex data type, for example:&lt;/p&gt;
&lt;p&gt;Say we have a little language that looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;name:string;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;age:number;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;active:boolean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can define a little syntax tree that we want our output to match as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Ast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Ast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name: Identifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;kind: Kind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Kind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  StringKind&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  BooleanKind&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  NumberKind&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Identifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Identifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name: String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; NodePart&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  NodeKind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;kind: Kind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  NodeIdentifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;identifier: Identifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;All of the above directly map to something within our syntax other than &lt;code&gt;NodePart&lt;/code&gt; which is used as an intermediate type that allows us to search for &lt;code&gt;Kind&lt;/code&gt; and &lt;code&gt;Identifier&lt;/code&gt; in the same &lt;code&gt;choice&lt;/code&gt; due to how Gleam generics work&lt;/p&gt;
&lt;p&gt;Finally, we can define a parser using the library I made as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // Parse an identifier&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; identifier &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    letters&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Identifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // Parse the different node &amp;quot;kinds&amp;quot; that the language has&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; string_kind &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;string&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map_token&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;StringKind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; number_kind &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;number&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map_token&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;NumberKind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; boolean_kind &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;boolean&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map_token&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;BooleanKind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; kind &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; choice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([string_kind, number_kind, boolean_kind])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // A node is defined as a sequence of (indeitifier, :)(kind, ;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; node &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    sequence&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(identifier, &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;:&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; label_error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(custom_error))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;NodeIdentifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      left&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(kind, &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;NodeKind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Extract the identifier and kind from our mapping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; try_map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ok) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      case&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ok {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;NodeIdentifier&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(i), &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;NodeKind&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(k)] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Ok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(i, k))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        _&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Failed to match identifier:kind&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; whitespace &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; regex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\\&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;s*&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parser &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; separator1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(node, whitespace) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Ast&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  parser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can use this to parse our initial input fragment which yields:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(input)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ParserState(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//    Ast([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//      Node(Identifier(&amp;quot;name&amp;quot;), StringKind),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//      Node(Identifier(&amp;quot;age&amp;quot;), NumberKind),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//      Node(Identifier(&amp;quot;active&amp;quot;), BooleanKind),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//    ]),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//    &amp;quot;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;That&amp;#39;s about it. At a high level you should be able to build parsers using the concepts I&amp;#39;ve mentioned here. Combinators are extremely powerful and I think can work as a great introduction to to functional programming concepts&lt;/p&gt;
&lt;h2&gt;The Library&lt;/h2&gt;
&lt;p&gt;Over the course of learning about parser combinators and the gleam language, I put together a little parsing library. It&amp;#39;s probably extremely inefficient but was a fun little project and I think it was a useful learning excercise. My libray can be found &lt;a href=&quot;https://github.com/sftsrv/parz&quot; &gt;on GitHub&lt;/a&gt; but it&amp;#39;s also published as a package that you can use on &lt;a href=&quot;https://hexdocs.pm/parz&quot; &gt;Hex&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;My time was primarily spent between the following resources when working on this project&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gleam.run/documentation/&quot; &gt;Gleam Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PLP29wDx6QmW5yfO1LAgO8kU3aQEj8SIrU&quot; &gt;Parser Combinators by Low Byte Productions on YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fsharpforfunandprofit.com/posts/understanding-parser-combinators&quot; &gt;Parser Combinators by Scott Wlaschin on F# for Fun and Profit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, if you just wan to learn to program in Gleam you can take a look on &lt;a href=&quot;https://exercism.org/tracks/gleam&quot; &gt;Exercism&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Additonally, some more generally related information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/docs/javascript/typescript-ast&quot; &gt;My notes on working with the Typescript AST&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>CSS @counter-style with Emojis</title><link>https://nabeelvalley.co.za/blog/2024/21-03/css-counter-style.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/21-03/css-counter-style.html</guid><description>Using the Counter-style attribute in CSS</description><pubDate>Thu, 21 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;CSS @counter-style with Emojis&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;The CSS &lt;code&gt;@counter-style&lt;/code&gt; rule is used for defining list-styles in CSS&lt;/p&gt;
&lt;p&gt;The syntax is pretty simple:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@counter-style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;counter-style-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  system&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;cyclic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;alphabetic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;|symblic|&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;fixed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  symbols&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;space&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; separated list of symbols&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  prefix&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; before &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;symbol&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  suffix&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; after &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;symbol&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* and some more options... */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /* take a look at the MDN doc for all the customizations you can do, it&amp;#39;s pretty cool */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Currently &lt;code&gt;symbols&lt;/code&gt; just supports strings, but once fully supported it will also be possible to use images as symbols&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Cyclic Counter Style&lt;/h2&gt;
&lt;p&gt;For the sake of example, I&amp;#39;ll be using Emojis as the symbols to display. We can define a cycle which uses some emojis like so:&lt;/p&gt;
&lt;site-snippet-preview&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;css-counter-style/cyclic.css&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@counter-style&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; emoji-cyclic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  system&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;cyclic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  symbols&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;🎈&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;✨&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;🎢&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;🧵&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;🛒&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;👓&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;🎨&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;🛝&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;🎻&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;📻&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;📺&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  suffix&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;➡️&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.emoji-cyclic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  list-style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: emoji-cyclic;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;div&gt;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;ul class=&quot;emoji-cyclic&quot; &gt;
  &lt;li&gt;Item 1&lt;/li&gt;
  &lt;li&gt;Item 2&lt;/li&gt;
  &lt;li&gt;Item 3&lt;/li&gt;
  &lt;li&gt;Item 4&lt;/li&gt;
  &lt;li&gt;Item 5&lt;/li&gt;
  &lt;li&gt;Item 7&lt;/li&gt;
  &lt;li&gt;Item 8&lt;/li&gt;
  &lt;li&gt;Item 9&lt;/li&gt;
  &lt;li&gt;Item 10&lt;/li&gt;
&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;&lt;style&gt;@scope {@counter-style emoji-cyclic {
  system: cyclic;
  symbols: &#39;🎈&#39; &#39;✨&#39; &#39;🎢&#39; &#39;🧵&#39; &#39;🛒&#39; &#39;👓&#39; &#39;🎨&#39; &#39;🛝&#39; &#39;🎻&#39; &#39;📻&#39; &#39;📺&#39;;
  suffix: &#39;➡️&#39;;
}

ul.emoji-cyclic {
  list-style: emoji-cyclic;
}
}&lt;/style&gt;&lt;/div&gt;&lt;/site-snippet-preview&gt;&lt;h2&gt;Numeric Counter Style&lt;/h2&gt;
&lt;p&gt;For this example, we&amp;#39;ll use emoji numbers for the counter style&lt;/p&gt;
&lt;site-snippet-preview&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;css-counter-style/numeric.css&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@counter-style&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; emoji-numeric&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  system&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;numeric&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  symbols&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;0️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;1️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;2️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;3️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;4️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;5️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;6️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;7️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;8️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;9️⃣&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  suffix&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ol&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.emoji-numeric&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  list-style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: emoji-numeric;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  list-style-position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;inside&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  padding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;div&gt;&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;div&gt;
  &lt;ol class=&quot;emoji-numeric&quot; &gt;
    &lt;li&gt;Item 1&lt;/li&gt;
    &lt;li&gt;Item 2&lt;/li&gt;
    &lt;li&gt;Item 3&lt;/li&gt;
    &lt;li&gt;Item 4&lt;/li&gt;
    &lt;li&gt;Item 5&lt;/li&gt;
  &lt;/ol&gt;
  &lt;ol class=&quot;emoji-numeric&quot; start=&quot;11&quot; &gt;
    &lt;li&gt;Item 11&lt;/li&gt;
    &lt;li&gt;Item 12&lt;/li&gt;
    &lt;li&gt;Item 13&lt;/li&gt;
    &lt;li&gt;Item 14&lt;/li&gt;
    &lt;li&gt;Item 15&lt;/li&gt;
  &lt;/ol&gt;
  &lt;ol class=&quot;emoji-numeric&quot; start=&quot;111&quot; &gt;
    &lt;li&gt;Item 111&lt;/li&gt;
    &lt;li&gt;Item 112&lt;/li&gt;
    &lt;li&gt;Item 113&lt;/li&gt;
    &lt;li&gt;Item 114&lt;/li&gt;
    &lt;li&gt;Item 115&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;&lt;style&gt;@scope {@counter-style emoji-numeric {
  system: numeric;
  symbols: &#39;0️⃣&#39; &#39;1️⃣&#39; &#39;2️⃣&#39; &#39;3️⃣&#39; &#39;4️⃣&#39; &#39;5️⃣&#39; &#39;6️⃣&#39; &#39;7️⃣&#39; &#39;8️⃣&#39; &#39;9️⃣&#39;;
  suffix: &#39; &#39;;
}

ol.emoji-numeric {
  list-style: emoji-numeric;
  list-style-position: inside;
  padding: 0;
}
}&lt;/style&gt;&lt;/div&gt;&lt;/site-snippet-preview&gt;&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@counter-style&quot; &gt;MDN @counter-style&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/predefined-counter-styles/&quot; &gt;W3C Predefined Counter Styles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://r12a.github.io/app-counters/&quot; &gt;Counter Style Converter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>A Visual Language for Image Manipulation</title><link>https://nabeelvalley.co.za/blog/2024/24-08/unintentionally-made-a-programming-language.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/24-08/unintentionally-made-a-programming-language.html</guid><description>I accidentally created a programming language for editing photos</description><pubDate>Sat, 24 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;A Visual Language for Image Manipulation&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I&amp;#39;ve spent the past few weeks building a concept photo editing application that allows users to visually define and compose shaders to transform an image in ways that are really challenging or impossible in other image manipulation software&lt;/p&gt;
&lt;p&gt;For readers of my website it&amp;#39;s probably not too much of a surprise that I&amp;#39;ve been spending a lot of time learning about &lt;a href=&quot;/blog/20-07/parser-combinators-and-gleam&quot; &gt;Parser Combinators&lt;/a&gt; as well as &lt;a href=&quot;/docs/shaders/intro-to-shaders&quot; &gt;Shaders&lt;/a&gt;. Armed with this information, it looks like I accidentally created a Visual Programming Language - this post will talk about how that all works&lt;/p&gt;
&lt;h2&gt;Why&lt;/h2&gt;
&lt;p&gt;Every time I&amp;#39;ve shown anyone the app the first question was &amp;quot;Why do you need this?&amp;quot;. I think it&amp;#39;s fair to say that no one &lt;em&gt;really&lt;/em&gt; &lt;strong&gt;needs&lt;/strong&gt; this. This exists to satisfy the artistic urge to do create something new. I&amp;#39;ve spent so much time feeling limited by the tools I have for working with images are lacking in creative expression. I think there&amp;#39;s an intersection between computational/generative art and photography that&amp;#39;s underserved and it&amp;#39;s a space I would like to play in. I wanted to create a tool that allows creative &lt;strong&gt;exploration&lt;/strong&gt; of images and helps break away from the &amp;quot;filter&amp;quot; based approach that dominates how we edit images&lt;/p&gt;
&lt;p&gt;It also seemed like a challenge, it begged to be done.&lt;/p&gt;
&lt;h2&gt;The App&lt;/h2&gt;
&lt;p&gt;The high level architecture that makes this all work looks something like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I define different types of functions that can be applied to an image using a shader function written in &lt;strong&gt;WebGPU&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The shader is then parsed into a &lt;strong&gt;Node&lt;/strong&gt; that a user can use in the editing workflow&lt;/li&gt;
&lt;li&gt;A user can structure &lt;strong&gt;Nodes&lt;/strong&gt; and &lt;strong&gt;Edges&lt;/strong&gt; into a tree for applying edits&lt;/li&gt;
&lt;li&gt;The tree is compiled into shader code and inputs to the shader (&lt;strong&gt;Bindings/Uniforms&lt;/strong&gt;) are identified&lt;/li&gt;
&lt;li&gt;The final shader is applied to image and is updated when a user modifies any &lt;strong&gt;Bindings&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Shaders&lt;/h2&gt;
&lt;p&gt;Shaders are programs that run on the GPU. Due to this fact there are some interesting limitations on how shaders work and what they can do. For working in our application a shader consists of two parts, a &lt;strong&gt;Vertex Shader&lt;/strong&gt; and a &lt;strong&gt;Fragment Shader&lt;/strong&gt;. The Vertex Shader is related to objects that are being rendered in a scene, since we&amp;#39;re rendering an image this isn&amp;#39;t of too much consequence, and for our purposes this always looks the same:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;struct VertexOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  @builtin(position) position: vec4f,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  @location(0) texcoord: vec2f,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@node fn vs(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  @builtin(node_index) nodeIndex : u32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;) -&amp;gt; VertexOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  const pos = array(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    vec2( 1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    vec2( 1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    vec2(-1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    vec2( 1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    vec2(-1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    vec2(-1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  var vsOutput: VertexOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  let xy = pos[nodeIndex];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  vsOutput.texcoord = pos[nodeIndex] * vec2f(0.5, 0.5) + vec2f(0.5);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  vsOutput.position = vec4f(pos[nodeIndex], 0, 1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  return vsOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The data output from the Vertex shader is sent to the Fragment shader. We&amp;#39;ve defined a struct for the data I want to pass called &lt;code&gt;VertexOutput&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The Fragment shader is where things get interesting though. This is where I apply transformations to pixel data and it allows us to do stuff to our image. For now I&amp;#39;ve defined the main part of our Fragment shader as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@group(0) @binding(0) var ourSampler: sampler;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@group(0) @binding(1) var ourTexture: texture_2d&amp;lt;f32&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;// BINDINGS_SECTION_START&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;// BINDINGS_SECTION_END&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@node fn sample(texcoord: vec2f) -&amp;gt; vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  return textureSample(ourTexture, ourSampler, texcoord);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@fragment fn fs(fsInput: VertexOutput) -&amp;gt; @location(0) vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  var input__result = fsInput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  // MAIN_SECTION_START&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  return textureSample(ourTexture, ourSampler, fsInput__result.texcoord);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  // MAIN_SECTION_END&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above I have also defined a function called &lt;code&gt;sample&lt;/code&gt; which has the &lt;code&gt;@node&lt;/code&gt; decorator - this is important - our app will use this decorator to identify methods that will be available in the UI that can be applied to images. The &lt;code&gt;sample&lt;/code&gt; decorator simply gets the color of a pixel in the input for a given coordinate. In fragment shader I need to output a color as denoted by the return type of the &lt;code&gt;fs&lt;/code&gt; function&lt;/p&gt;
&lt;p&gt;From the perspective of a shader our goal is to provide a library of functions that apply transformations that users can compose to apply an edit to an image, a simple example of this are the &lt;code&gt;splitChannels&lt;/code&gt; and &lt;code&gt;combineChannels&lt;/code&gt; functions that we can see below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;struct SplitChannelsOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  r: f32,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  g: f32,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  b: f32,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  a: f32,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@node fn splitChannels(color: vec4f) -&amp;gt; SplitChannelsOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  var output: SplitChannelsOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  output.r = color.r;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  output.g = color.g;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  output.b = color.b;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  output.a = color.a;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  return output;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@node fn combineChannels(r: f32, g: f32, b: f32, a: f32) -&amp;gt; vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  return vec4f(r, g, b, a);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The above methods can be composed in interesting ways to do things like swap around the green and blue channels of an image:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@fragment fn fs(fsInput: VertexOutput) -&amp;gt; @location(0) vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var split = splitChannels(color);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var result = combineChannels(color.r, color.b, color.g, color.a);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    return result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So this is the basic concept, a bit of complexity comes in when we consider that it&amp;#39;s possible that a function may want inputs from multiple other functions but this still doesn&amp;#39;t create too much of a hurdle for us as we&amp;#39;ll discuss later&lt;/p&gt;
&lt;h2&gt;Parsing&lt;/h2&gt;
&lt;p&gt;I wanted to ensure that the application has a single source of truth for the available functions. In order to do this I wanted to use the shader to inform us as to what functions should be available for a user. In order to do this I had to create a parser for the WebGPU langauge. The parser I built is a little simplified since there are only certain things I care about when parsing the shader. It&amp;#39;s also optimized for maintenance and probably isn&amp;#39;t very fast. My main goal here was to get something working. I wrote the parser using a library called &lt;a href=&quot;https://github.com/microsoft/ts-parsec&quot; &gt;&lt;code&gt;ts-parsec&lt;/code&gt;&lt;/a&gt; which lets me define parsers using parser combinators.&lt;/p&gt;
&lt;p&gt;Defining a parser using this library requires a list of tokens to be defined using regexes. Below are the tokens I currently have defined:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;enum&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Tok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Var&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Var&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Let&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Let&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Const&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Const&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Struct&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Struct&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Return&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Fn&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Fn&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  At&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;At&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Arrow&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Arrow&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Integer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Integer&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Comma&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Comma&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Dot&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Dot&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Plus&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Plus&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Semicolon&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Semicolon&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Colon&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Colon&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Dash&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Dash&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Asterisk&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Asterisk&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Slash&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Slash&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Equal&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Equal&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  OpenParen&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;OpenParen&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  CloseParen&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;CloseParen&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  OpenBrace&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;OpenBrace&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  CloseBrace&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;CloseBrace&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  OpenBracket&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;OpenBracket&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  CloseBracket&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;CloseBracket&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  OpenAngle&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;OpenAngle&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  CloseAngle&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;CloseAngle&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Identifier&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Identifier&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Space&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Space&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  Comment&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;Comment&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Along with the tokenizer. Each token is configured as &lt;code&gt;[shouldKeepToken, regex, token]&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; tokenizer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;buildLexer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;var/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Var],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;let/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Let],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;const/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Const],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;struct /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Struct],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;fn/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Fn],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;return/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Return],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;-&amp;gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Arrow],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;@/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.At],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;,/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Comma],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\.&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Dot],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Plus],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Semicolon],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Colon],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\-&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Dash],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\*&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Asterisk],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\/&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Slash],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Equal],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.OpenParen],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\)&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.CloseParen],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\{&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.OpenBrace],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\}&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.CloseBrace],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.OpenBracket],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.CloseBracket],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.OpenAngle],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.CloseAngle],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\d&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+?&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Integer],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[A-Za-z]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[A-Za-z0-9_]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Identifier],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\s&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Space],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\/\/&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; .&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, Tok.Comment],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can see that I throw away comments and spaces since I don&amp;#39;t care about these for now&lt;/p&gt;
&lt;p&gt;A relatively simple parser that I have is&lt;/p&gt;
&lt;p&gt;All parsers in my application are defined using classes to just help keep things a little tidy. One of the simpler parsers I have is the one that parses integers and is defined as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Integer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;apply&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Tok.Integer), (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Integer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.text))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This consists of a constructor for defining the members and a &lt;code&gt;static parser&lt;/code&gt; function which defines a parser for the current class. We can compose these parsers to build more complex ones, for example the way I parse &lt;code&gt;Generic&lt;/code&gt; uses &lt;code&gt;Integer&lt;/code&gt; for an optional &lt;code&gt;length&lt;/code&gt; that a generic may have, for example &lt;code&gt;array&amp;lt;f32, 3&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Generic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TypeDeclaration&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    public&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Integer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;apply&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;kmid&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Tok.OpenAngle),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;seq&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        TypeDeclaration.parser,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;opt&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;kright&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Tok.Comma), Integer.parser)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ts.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;tok&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(Tok.CloseAngle),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;matches&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Generic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;matches),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The composition of these parses results in a tree looking something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;TypeDeclaration {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Generic {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;length&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Integer {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;quot;value&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: TypeDeclaration {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;quot;generic&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;      &amp;quot;identifier&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Identifier {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;i32&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;  &amp;quot;identifier&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: Identifier {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;    &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;array&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;At a high level, we can apply this to the entire file to get a syntax tree for the whole file, but as you can imagine that starts to get much bigger&lt;/p&gt;
&lt;h2&gt;The UI&lt;/h2&gt;
&lt;p&gt;Now, since I&amp;#39;m able to parse the file, I can extract the functions from it and use that to define the different things a user can do in the UI. A simple example of some UI that uses the &lt;code&gt;sample&lt;/code&gt; function defined previously can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.778498609823911&quot; orientation=&quot;horizontal&quot; alt=&quot;sample&quot; src=&quot;/optimized-images/content/pages/blog/2024/24-08/sample.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;In this we are able to define Nodes that have certain inputs and outputs which can be connected to each other. Each node is a function call and each edge refers to using the result of one function as an input to another function. When defining connections it&amp;#39;s important to verify that connections are of the same type and don&amp;#39;t create a cycle in any way - while fiddly, the code to do this isn&amp;#39;t particularly interesting&lt;/p&gt;
&lt;p&gt;This step is actually relatively simple, the complexity comes into converting this back to the WebGPU code.&lt;/p&gt;
&lt;h2&gt;Compiling&lt;/h2&gt;
&lt;p&gt;This tree structure effectively represents a &lt;strong&gt;Dependency Graph&lt;/strong&gt; where all functions depend on their inputs, and the final &lt;code&gt;output&lt;/code&gt; node depends on any previous edges. The goal in this step is to build a tree out of the nodes and edges and then sort this in a way that defines the order that different operations need to be applied to obtain the &lt;code&gt;output&lt;/code&gt; value&lt;/p&gt;
&lt;p&gt;The first step to this is compiling a list of &lt;code&gt;nodes&lt;/code&gt; and &lt;code&gt;edges&lt;/code&gt; into a &lt;code&gt;tree&lt;/code&gt;. I&amp;#39;ve done this using the following:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReadonlyOrderedMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ReadonlyMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  orderedValues&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReadonlyArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  orderedKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReadonlyArray&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Wraps the builtin `Map` with an easy way to get keys and values as an array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * sorted by the original insertion order&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@see&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MDN:&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; [Map is insertion-order aware](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; OrderedMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;implements&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ReadonlyOrderedMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  orderedValues&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Array.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;values&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  orderedKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Array.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;keys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; buildTree&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Node&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Edge&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  nodes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  edges&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; E&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; OrderedMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Connected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OrderedMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Connected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; node&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; nodes) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    map.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;set&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(node.id, { &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;node, connections: [] })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; edge&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; edges) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; from&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; map.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(edge.from)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; map.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(edge.to)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (from &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; to) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      from.connections.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([edge, to])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; map&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This helps us go from the list of connections to a tree that represents the relationships between the nodes - this looks pretty much the same as the UI from earlier&lt;/p&gt;
&lt;p&gt;Next, we need to sort the nodes in an order that ensures that each node comes after any nodes that it depends on, this is called a &lt;strong&gt;Topographic Sort&lt;/strong&gt; and I&amp;#39;ve loosely implemented it as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Does a depth-first search on the input vertices relative to the given ID.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@returns&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; a map of the nodes reachable from&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; topologicalSort&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Vertex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Edge&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  vertices&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReadonlyMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Connected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  relative&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; visited&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; OrderedMap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Connected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; rec&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;at&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Connected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;E&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (visited.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;has&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(at.id)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;_&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;child&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; at.connections) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;rec&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(child)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Insert self after all children have been inserted to maintain ordering&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    visited.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;set&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(at.id, at)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; initial&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; vertices.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(relative)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;initial) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Relative node not in tree&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, relative, vertices)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;Relative node not provided&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  rec&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(initial)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; visited&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using this function, I can transform the earlier example for sampling an image into a list that looks something like &lt;code&gt;[input, sample, output]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;What&amp;#39;s nice is that this will also work with a more complicated set of connections like so:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.778498609823911&quot; orientation=&quot;horizontal&quot; alt=&quot;complex&quot; src=&quot;/optimized-images/content/pages/blog/2024/24-08/complex.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Can be compiled into &lt;code&gt;[input, sample, splitChannels, combineChannels, brighten, output]&lt;/code&gt;. It&amp;#39;s worth taking a moment to let this idea sink in because this is the core idea that allows us to compile the UI based language into a shader&lt;/p&gt;
&lt;p&gt;Once we are able to order our nodes, it&amp;#39;s a simple matter of iterating through them in order and determining which inputs are needed and which functions these nodes refer to, the output of this looks something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@fragment fn fs(fsInput: VertexOutput) -&amp;gt; @location(0) vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value1 = sample(input.texcoord);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value2 = splitChannels(value1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value3 = combineChannels(value2.g, value2.r, value2.b, value2.a);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value4 = brighten(value3, value2.b);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    return value4;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;User Input&lt;/h2&gt;
&lt;p&gt;So, it&amp;#39;s all well and good that I can compile a shader, but as I have it right now a user can&amp;#39;t really customize what any of these values do. It would be nice if I could allow users to provide some input to the shader. For this we will use a &lt;strong&gt;uniform&lt;/strong&gt; which is basically an input to the GPU. Uniforms are nice because we can change them without having to recompile the shader&lt;/p&gt;
&lt;p&gt;For my purpose, I can infer that any input to a node that is not specified is meant to be set by the user, we can depict this using some kind of input field for that value, in the example below we use a range input for a &lt;code&gt;f32&lt;/code&gt; value, this can be set by the user:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.780148423005566&quot; orientation=&quot;horizontal&quot; alt=&quot;input&quot; src=&quot;/optimized-images/content/pages/blog/2024/24-08/input.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;Then, when compiling our nodes, we can extract this to a &lt;code&gt;binding&lt;/code&gt;, which would look something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@group(1) @binding(0) var&amp;lt;uniform&amp;gt; combineChannelsInputB: f32;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And that can be used in the fragment shader as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgpu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;@fragment fn fs(fsInput: VertexOutput) -&amp;gt; @location(0) vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value1 = sample(input.texcoord);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value2 = splitChannels(value1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value3 = combineChannels(value2.g, value2.r, combineChannelsInputB, value2.a);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    var value4 = brighten(value3, value2.b);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    return value4;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, actually passing this value to the shader is a bit messy but really comes down to using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API&quot; &gt;WebGPU API&lt;/a&gt;. This effectively involves creating a &lt;code&gt;bindGroup&lt;/code&gt; adding &lt;code&gt;buffers&lt;/code&gt; which hold the value of the data&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dynamicBuffers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;BindingId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;GPUBuffer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; entries&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; GPUBindGroupEntry&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;bindings&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; shader.compiled.compiledNodes) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; binding&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; bindings) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; buffer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createBuffer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      size: binding.size,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      usage: GPUBufferUsage.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;UNIFORM&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; GPUBufferUsage.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;COPY_DST&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      label: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;dynamic binding for: &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; binding.declaration,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    buffer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;unmap&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    entries.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;push&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      binding: binding.binding,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      resource: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        buffer,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    dynamicBuffers[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;id&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;binding&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; buffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dynamicBindGroup&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  entries.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createBindGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    label: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;dynamic bind group&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    layout: pipeline.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getBindGroupLayout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    entries,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Whenever the user changes some input the buffer values can be updates like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;groupId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Object.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;entries&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {})) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;bindingId&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;of&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Object.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;entries&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(group &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {})) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; buffer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dynamicBuffers[&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;groupId&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}.${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;bindingId&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (buffer) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      device.queue.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;writeBuffer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(buffer, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, there are some finicky bits involved in assembling all the data here but these are the important bits around using the API&lt;/p&gt;
&lt;h2&gt;Closing&lt;/h2&gt;
&lt;p&gt;As you can see there are quite a few moving pieces but I feel like the approach I&amp;#39;ve taken here fits the problem relatively well. As things are defined now, all app functionality is driven by what is available in the shader and the different nodes can be inferred and combined however the user wants&lt;/p&gt;
&lt;p&gt;This isn&amp;#39;t the end though. There&amp;#39;s a lot more to do, and a lot of art to be made&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;The most important resource in making this work is defintely the &lt;a href=&quot;https://webgpufundamentals.org/&quot; &gt;WebGPU Fundamentals Site&lt;/a&gt;. The UI is inspired by &lt;a href=&quot;https://www.blender.org/&quot; &gt;Blender&amp;#39;s&lt;/a&gt; Node Editor and is implemented using &lt;a href=&quot;https://reactflow.dev/&quot; &gt;React Flow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the purpose of implementation, I&amp;#39;ve also looked at loads of different things, of notable value were the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/WGSL&quot; &gt;WGSL Spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webgpufundamentals.org/&quot; &gt;WebGPU Fundamentals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://alain.xyz/&quot; &gt;Alan Galvan&amp;#39;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://maximmcnair.com/&quot; &gt;Maxim McNair&amp;#39;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=vPEiCNjjjFU&quot; &gt;WebGPU Course by GetIntoGameDev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/topological-sorting/&quot; &gt;Topographical Sorting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/microsoft/ts-parsec&quot; &gt;&lt;code&gt;ts-parsec&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reactflow.dev/&quot; &gt;React Flow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>week 34, year 2024 - programming languages of various types</title><link>https://nabeelvalley.co.za/blog/2024/24-08/week-34-programming-languages-of-various-types.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/24-08/week-34-programming-languages-of-various-types.html</guid><pubDate>Sat, 24 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;week 34, year 2024 - programming languages of various types&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;what i&amp;#39;m working on&lt;/h2&gt;
&lt;p&gt;i&amp;#39;ve been putting some hours into my image editing app and think i have something that technically works, at the moment it doesn&amp;#39;t look like much but proves that the visual programming language idea works:&lt;/p&gt;
&lt;p&gt;i wrote a &lt;a href=&quot;https://nabeelvalley.co.za/blog/2024/24-08/unintentionally-made-a-programming-language/&quot; &gt;blog post explaining how the application works&lt;/a&gt;{rel=&amp;quot;nofollow ugc noopener&amp;quot;} which explains the concepts around everything all the way from shaders to the ui&lt;/p&gt;
&lt;h2&gt;what i found&lt;/h2&gt;
&lt;p&gt;this week was pretty busy but i managed to get some time to speak to some other devs and we got chatting about configuration languages&lt;/p&gt;
&lt;h3&gt;rcl&lt;/h3&gt;
&lt;p&gt;i bumped into &lt;a href=&quot;https://github.com/ruuda&quot; &gt;Ruud&lt;/a&gt;{rel=&amp;quot;nofollow ugc noopener&amp;quot;} who works on a &lt;a href=&quot;https://github.com/ruuda/rcl&quot; &gt;reasonable configuration language&lt;/a&gt;{rel=&amp;quot;nofollow ugc noopener&amp;quot;} which a language for defining configuration that outputs to more common formats like json&lt;/p&gt;
&lt;h3&gt;pkl&lt;/h3&gt;
&lt;p&gt;this chat also reminded my about &lt;a href=&quot;https://github.com/apple/pkl&quot; &gt;another configuration language made by apple&lt;/a&gt;{rel=&amp;quot;nofollow ugc noopener&amp;quot;} which was released a while ago and is a language for config as code with support for validation&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>On Automatic Lensess</title><link>https://nabeelvalley.co.za/blog/2024/27-04/automatic-lenses.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/27-04/automatic-lenses.html</guid><description>Why automatic camera lenses suck</description><pubDate>Sat, 27 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;On Automatic Lensess&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I enjoy capturing the world around me - places, people, plants - anything the light touches really&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve also spent a fair number of years shooting with manual focus lenses. Every now and then I pick up an auto focus lens - usually my kit lens, usually because I&amp;#39;m experimenting with a focal length or style I don&amp;#39;t use often&lt;/p&gt;
&lt;p&gt;Between a museum and getting a bite to eat I was strolling the streets of Amsterdam trying to catch some of the Kingsday activities. I used my kit lens most of the time. It&amp;#39;s a 15-45mm f3.5 Fujifilm lens that&amp;#39;s fully automatic&lt;/p&gt;
&lt;p&gt;Recently I&amp;#39;ve been experimenting with shooting at f11-f22 and aperture priority mode while prefocusing to get some more &amp;quot;classic style&amp;quot; street photos. This setup is really great because it means I don&amp;#39;t have to fiddle with anything when trying to get a shot - I can just lift my camera and click. This is especially handy since a scene can change quickly when shooting on a busy street&lt;/p&gt;
&lt;p&gt;While shooting today I noticed a few things that annoyed me quite a bit and thought I should put them down mostly as a reminder to myself as to why I don&amp;#39;t really shoot with automatic lenses&lt;/p&gt;
&lt;p&gt;Firstly, I get the feeling that automatic lenses make the process of turning a camera on and off a lot slower - I also get the feeling that it consumes a lot more battery life when turning on or off since the lens I have, and other lenses I&amp;#39;ve had previously, have a &amp;quot;collapsed&amp;quot; mode when inactive in which the lens elements are all fitted into the housing - when turned on, the motors in the lens &amp;quot;uncollapse&amp;quot; them which takes a bit of time and seems to eat a lot more battery than when using a fully manual lens&lt;/p&gt;
&lt;p&gt;Next, then lens I have uses &amp;quot;fake&amp;quot; focus and zoom rings (it&amp;#39;s a fully auto lens as opposed to just auto-focus). I find this extremely annoying when shooting because I can&amp;#39;t trust that my camera is going to retain my zoom or focus settings when turning it on or off or that they weren&amp;#39;t randomly changed at some time accidentally&lt;/p&gt;
&lt;p&gt;Semi related to this is that due to the focus and zoom rings being electronic, I don&amp;#39;t have any visible zoom or focus indicators on the lens. This means that I have to look through my camera to focus or zoom. This is a little annoying when shooting quickly because it means I can only change these settings after raising the camera to my eye - by the time I&amp;#39;ve dialed the settings in my shot is gone&lt;/p&gt;
&lt;p&gt;You can see the indicators I&amp;#39;m referring to below when comparing the two lenses I currently use&lt;/p&gt;
&lt;p&gt;The fully automatic Fujifilm 15-45mm f3.5 kit lens:&lt;/p&gt;
&lt;center style=&quot;max-width: 500px; margin: auto;&quot; &gt;&lt;p&gt;&lt;img aspect-ratio=&quot;1.0&quot; orientation=&quot;vertical&quot; alt=&quot;fuji15-45mm&quot; src=&quot;/optimized-images/public/content/blog/2024/27-04/fuji15-45mm.webp&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;A fully manual TTArtisan 35mm f1.4 lens:&lt;/p&gt;
&lt;center style=&quot;max-width: 500px; margin: auto;&quot; &gt;&lt;p&gt;&lt;img aspect-ratio=&quot;1.0&quot; orientation=&quot;vertical&quot; alt=&quot;ttartisan35mm&quot; src=&quot;/optimized-images/public/content/blog/2024/27-04/ttartisan35mm.webp&quot; &gt;&lt;/p&gt;
&lt;/center&gt;&lt;p&gt;Normally when shooting you need to set the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Focus&lt;/li&gt;
&lt;li&gt;Zoom&lt;/li&gt;
&lt;li&gt;ISO&lt;/li&gt;
&lt;li&gt;Aperture&lt;/li&gt;
&lt;li&gt;Shutter speed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If I have my focus set before even raising the camera, that&amp;#39;s about more than half of my time-to-shot saved - it&amp;#39;s really handy - particularly with lenses that have slow zoom or focus response like the Fuji lens&lt;/p&gt;
&lt;p&gt;Higher end cameras (particularly Fujifilm cameras) also have the ISO and shutter dials at the top of the camera so that you can view these settings on the hardware without having to turn the camera on - this way you&amp;#39;re always ready to shoot&lt;/p&gt;
&lt;p&gt;Lastly - aperture. Fully manual lenses also have manual aperture rings. This means that on a fully manual lens, even on a lower end camera - at a glance I can view 3 of the 5 things I need to set up in order to take a picture&lt;/p&gt;
&lt;p&gt;Okay, so what? Just remember the settings right? Most cameras should retain your settings between restarts so this doesn&amp;#39;t really matter too much, and generally you&amp;#39;re not changing settings without knowing what your camera and light meter are showing you right? right?&lt;/p&gt;
&lt;p&gt;Well ... not exactly&lt;/p&gt;
&lt;p&gt;So, when shooting street there&amp;#39;s a concept called &amp;quot;shooting from the hip&amp;quot; which is effectively shooting without having to pick up your camera at all. When doing this it can be useful (if not absolutely necessary) to set your camera focus and zoom while not actively shooting so that you can be ready when something comes up - when you&amp;#39;re working with a mirrorless camera, this is even more useful since it lets you conserve battery life if your camera is off while doing this&lt;/p&gt;
&lt;p&gt;However, there are certain cases where being able to have a lens that is automatic is useful like in video for example, when smooth focusing and zooming can make or break a shot, or for photographers who are just starting out and want to let their camera control their aperture or focus settings so they can focus on just getting the shot&lt;/p&gt;
&lt;h2&gt;Some Technical Jargon&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Focal Length&amp;quot; not &amp;quot;Zoom&amp;quot;&lt;/li&gt;
&lt;li&gt;I don&amp;#39;t know what lenses that have electronically controlled focus and zoom rings are called, I&amp;#39;ve settled for &amp;quot;Automatic Lenses&amp;quot;&lt;/li&gt;
&lt;li&gt;The zoom thing obviously doesn&amp;#39;t apply to lenses that do not zoom&lt;/li&gt;
&lt;li&gt;The aperture thing obviously doesn&amp;#39;t apply to lenses that don&amp;#39;t have an aperture control&lt;/li&gt;
&lt;li&gt;All of this also probably doesn&amp;#39;t apply to cameras that are fully manual&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>An unexpected way to open links in the terminal</title><link>https://nabeelvalley.co.za/blog/2024/28-08/open-terminal-links-in-vscode.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/28-08/open-terminal-links-in-vscode.html</guid><description>A little shortcut for opening terminal links in VSCode</description><pubDate>Wed, 28 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;An unexpected way to open links in the terminal&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I accidentally hit &lt;code&gt;cmd + shift + o&lt;/code&gt; while in the terminal on VSCode which popped open a little window to navigate to the links to files that were currently printed out in my terminal - this seems like a more keyboard friendly way to do &lt;code&gt;cmd + click&lt;/code&gt; on a link in the terminal&lt;/p&gt;
&lt;p&gt;Upon further investigation it looks like the following is a thing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When in the terminal, after running some command&lt;/li&gt;
&lt;li&gt;Find a link (URL or file) that you want to open&lt;/li&gt;
&lt;li&gt;Use the command pallette with &lt;code&gt;cmd + shift + p&lt;/code&gt; and use the &lt;code&gt;Terminal: Open Detected Link ...&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;Browse the links, if it&amp;#39;s a file you&amp;#39;ll automatically preview the file, click enter to select a file or link to open&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tadaa, that&amp;#39;s about it - an accidental shortcut that I&amp;#39;ll most definitely be using in the future&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Type safe URL templates</title><link>https://nabeelvalley.co.za/blog/2024/31-10/type-safe-url-templates.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2024/31-10/type-safe-url-templates.html</guid><description>Making URL template replacements safe</description><pubDate>Thu, 31 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Type safe URL templates&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;I don&amp;#39;t think the below is a good idea, but I thought it was a fun little Typescript excercise so here you go&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Something I see as a sort of recurring pattern is people doing template replacements in URLs, particularly something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; template&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;/users/{userId}/projects/{projectId}&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, while you can more simply make this template a function like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; template&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;projectId&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `/users/${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;userId&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}/projects/${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;projectId&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For some reason people don&amp;#39;t like to do that, I think it&amp;#39;s that it looks like a lot of duplication and perhaps they just don&amp;#39;t believe in making their own functions (who am I to know)&lt;/p&gt;
&lt;p&gt;More often than I&amp;#39;d like, I instead see people doing this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; template&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;/users/{userId}/projects/{projectId}&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// later&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; template.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;{userId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, userId).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;{projectId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, projectId)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;I think this is horrible, and while it works, it&amp;#39;s quite brittle and unless it&amp;#39;s got some tests or other means of verifying that this works it&amp;#39;s a really quick source of bugs for when things change, for example if you add or remove a parameter from the URL&lt;/p&gt;
&lt;p&gt;Now, I&amp;#39;m a huge fan of using the compiler to derive as much correctness as possible, even before even really thinking about tests, so when looking at something like this all I can think is that the TypeScript compiler can solve this&lt;/p&gt;
&lt;p&gt;I&amp;#39;m not saying that you should do what I&amp;#39;m about to present here, I think you&amp;#39;re probably better off using the method of a template being a simple function above, but I think it&amp;#39;s a fun little mental excercise&lt;/p&gt;
&lt;h2&gt;The Typescriptssss&lt;/h2&gt;
&lt;p&gt;Firstly, we need to parse this URL template things, this is simple enough using a little recursive type:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Extracts the keys from the URL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    TUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}{${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Param&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}}${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Param&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Rest&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; never&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, since in a URL all keys need to be a string at the end, we can define an object for URLs that uses this to define a record:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Uses the keys to define a record in which each key of the URL can be assigned to a string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;PathKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;A little test of the above types shows us:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Keys&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathKeys&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;/users/{userId}/projects/{projectId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   ^? type Keys = &amp;quot;userId&amp;quot; | &amp;quot;projectId&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Params&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;/users/{userId}/projects/{projectId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//   ^? type Params = { userId: string; projectId: string; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So great, that works and we can use that as the basis for building up more general function for creating these &amp;quot;safe urls&amp;quot;&lt;/p&gt;
&lt;p&gt;Before we go there though, let&amp;#39;s take a moment to think about the result of this URL. Now we could return the URL as a &lt;code&gt;string&lt;/code&gt; but since we&amp;#39;re being strict it would be nice to inform downstream consumers of what this string is made up of. Using a very similar method to how the &lt;code&gt;PathKeys&lt;/code&gt; type was done we can create a type for the result of a URL where the params have been replaced&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * Represents a URL in which all params have been substituted&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReplacedUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    TUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Base&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}{${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; _&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}}${&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;infer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Rest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Base&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}${&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ReplacedUrl&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Rest&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    :&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TUrl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Lastly, we can define the implementation of the URL replacer which is effectively just calling the &lt;code&gt;String.replace&lt;/code&gt; method on an input URL while using a strong type for the URL:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createTypedUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; TUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;params&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PathParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; url.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\{&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\w&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-light-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold&quot; &gt;\}&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;val&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; key&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;slice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (params &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Record&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;)[key] &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; val&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ReplacedUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;TUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using this looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; template&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;/users/{userId}/projects/{projectId}&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; as&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * A little factory for making typed URLs from the given template&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; typedUrl&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createTypedUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(template)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;//    ^? const typedUrl: (params: PathParams&amp;lt;&amp;quot;/users/{userId}/projects/{projectId}&amp;quot;&amp;gt;) =&amp;gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; typedUrl&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    userId: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;123&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    projectId: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;456&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ^? const url: `/users/${string}/projects/${string}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(url) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// &amp;#39;/users/123/projects/456&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, is this better than random string replacements? Yes. Is it better than just using string interpolation? No.&lt;/p&gt;
&lt;p&gt;While this isn&amp;#39;t something I recommend using I think the idea about thinking of underlying structure of common data types is important and something that&amp;#39;s worth thinking about in order to define more complete solutions &lt;/p&gt;
&lt;p&gt;Lastly, if you&amp;#39;re into this type of thing, take a look at some of my other TS shenanigans:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2024/16-08/optional-parameters-and-overloads-in-typescript&quot; &gt;Parameters, but only sometimes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2024/15-08/handling-complex-typescript-generics&quot; &gt;More generic than it should be&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2022/13-12/typescript-utilities&quot; &gt;Typescript Utilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/2023/09-05/generic-transformer-typescript&quot; &gt;Generic Object Property Formatter and Validator using Typescript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Scripting Text Manipulation</title><link>https://nabeelvalley.co.za/blog/2025/01-08/scripting-text-manipulation.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/01-08/scripting-text-manipulation.html</guid><description>An idea for automating changes to text files</description><pubDate>Fri, 01 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Scripting Text Manipulation&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;This is kind of just a brain dump of some things that I think would be interesting to explore&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, I&amp;#39;ve been using &lt;a href=&quot;https://zed.dev&quot; &gt;Zed&lt;/a&gt; a bit recently and have particularly enjoyed how it&amp;#39;s &lt;a href=&quot;https://zed.dev/docs/multibuffers&quot; &gt;MultiBuffers&lt;/a&gt; work. MultiBuffers basically allow you to simultaneously edit multiple files at once while also having things like syntax highlighting and language server support&lt;/p&gt;
&lt;p&gt;I really &lt;em&gt;wanted&lt;/em&gt; to add Zed to my toolchain because of this feature but it doesn&amp;#39;t quite seem to be a good fit in lots of other ways&lt;/p&gt;
&lt;p&gt;That being said - I really want multi buffer editing now so naturally my mind has shifted to thinking about how building something like this that meshes well with my workflow could look&lt;/p&gt;
&lt;p&gt;There are two levels that I could see something like this working on and are basically what I&amp;#39;d like to explore at some point, the ideas are basically:&lt;/p&gt;
&lt;h2&gt;1. Literally just implementing MultiBuffers&lt;/h2&gt;
&lt;p&gt;Yup. Basically have some kind of method that lets you do a search and open that using a utility that can the flush the changes back to the original files&lt;/p&gt;
&lt;p&gt;Imagine I want to edit all usages of the word &amp;quot;hello&amp;quot;, I could have a buffer that&amp;#39;s opened in my code editor via &lt;code&gt;my-search &amp;#39;hello&amp;#39; | my-edit | my-save&lt;/code&gt; or something like that, where the result of the search command would give us something that looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;--- start my/file/path1.txt:120-122&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;some context lines&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;hello world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;some more context&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;--- end my/file/path1.txt:120-122&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;--- start my/file/path2.txt:10-12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;some context lines&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;hello world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;some more context&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;--- end my/file/path2.txt:120-10-12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Making any changes to that would then update the ranges in the underlying files. This is nice because we can possibly do something like apply a macro to all instances of the word &lt;code&gt;hello&lt;/code&gt; across what looks like a single file. Which can then be saved an applied&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This could also be a simplified &lt;code&gt;git patch&lt;/code&gt; view which is tweaked to make editing nice, the advantage of this is that applying this patch could be done just using git if it can be normalized back to a patch when saving&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, there are still some challenges here that I&amp;#39;d still like to solve, like searching but getting the containing function instead of just some random range of files, which is why I think the search tool for producing these ranges also needs to be sufficiently smart&lt;/p&gt;
&lt;p&gt;There are lots of other quality things that do come up, for example getting LSP support within these edit-blocks, but I think that&amp;#39;s possibly doable. VSCode has something called &lt;a href=&quot;https://code.visualstudio.com/api/language-extensions/embedded-languages&quot; &gt;Embedded Programming Languages&lt;/a&gt; but if something like this could make it&amp;#39;s way through to the Language Server Protocol at large there could be a really cool user experience. But anyways, that&amp;#39;s not part of this solution&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that idea here isn&amp;#39;t to solve this for any specific editor but rather to create a composable solution that can work with any text editor and provide a nice mechanism to efficiently enable multi file editing&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;2. A language for text manipulation&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve mentioned &lt;a href=&quot;https://en.wikipedia.org/wiki/Macro_(computer_science)&quot; &gt;macros&lt;/a&gt;, in the context of code editors this typically refers to some kind of key you can press that triggers a predefined set of other keypresses (hopefully not recursively) that enables some relatively complex editing behavior. This is really powerful with tools like &lt;a href=&quot;https://www.vim.org&quot; &gt;Vim&lt;/a&gt;,  &lt;a href=&quot;https://www.gnu.org/software/emacs/&quot; &gt;Emacs&lt;/a&gt; , or Helix which allow users to repeat certain sets of changes, for example I may want to tell the editor to &lt;strong&gt;go to first word of line, change it to X, go to end of line, add semicolon&lt;/strong&gt; and then I&amp;#39;d record a macro which may be interpreted as &lt;code&gt;I&amp;lt;esc&amp;gt;wdiX&amp;lt;space&amp;gt;&amp;lt;esc&amp;gt;A;&amp;lt;esc&amp;gt;&lt;/code&gt; in Helix&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The sequence can look scary but remember that it&amp;#39;s an artifact of what we did, and not something we set out to create from the start&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, what if I wanted to create these sequences from scratch and have them applied to a file? Well, the Emacs people have solved this by the looks of it, there are two tools for doing it, namely:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nongnu.org/txr/&quot; &gt;TXR&lt;/a&gt; which seems really complicated? IDK how this is even meant to be used&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Silex/elmacro&quot; &gt;elmacro&lt;/a&gt; which looks like it&amp;#39;s got a really nice API for writing macros but seems to run inside of Emacs which isn&amp;#39;t what I&amp;#39;m looking for&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The elmacros API seems really nice, here&amp;#39;s the snippet from the docs:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;emacs-lisp&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;defun&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; upcase-last-word&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;interactive&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;move-end-of-line&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;backward-word&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;upcase-word&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;move-beginning-of-line&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;next-line&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;I think this is a great example of a language for manipulating text&lt;/p&gt;
&lt;p&gt;So my proposal is then - can we make something like this that can be run in isolation and has context awareness to some extent while still being generic enough to avoid language-specific things (like &lt;a href=&quot;/docs/javascript/typescript-ast&quot; &gt;AST based text transformers&lt;/a&gt;)?&lt;/p&gt;
&lt;p&gt;Basically take some file like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;hello world&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;hello bob&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And use a script which in psuedo code may look like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;# assume the &amp;quot;cursor&amp;quot; is at the start of the file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;for-each search `hello`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  # goes to &amp;#39;world&amp;#39; or &amp;#39;bob&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  go-to-next-word-start&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  # selects &amp;#39;world&amp;#39; or &amp;#39;bob&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  select $id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    go-to-end-of-word&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  end select&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  # searches for the containing &amp;#39;h1&amp;#39; or &amp;#39;p&amp;#39; tag&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  go-to (previous `&amp;lt;h1`) or (previous or `&amp;lt;p`)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  # writes some text using the previously selected text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  append `id=&amp;quot;$id&amp;quot;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;end for-each&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;To turn it into this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;hello world&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;bob&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;hello bob&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;span&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This would allow us to define a macro for doing the manipulation above and could allow us to make mass changes to a single file&lt;/p&gt;
&lt;p&gt;The code focus of this macro-style script would be that it&amp;#39;s quick to write and modify, but doesn&amp;#39;t have to scale since it&amp;#39;s intended for on-the-fly, once-off modifications, much like how you&amp;#39;d use macros normally&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It could also be really cool to make it possible to extract this from a Vim/Helix macro which can then be re-run in isolation or over a bunch of files&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Bringing it together&lt;/h2&gt;
&lt;p&gt;So these two ideas seem quite different. One of them provides a method for editing many files at once in an interactive manner, and the other automates edits to a single file. I&amp;#39;ve proposed these two because I think that they&amp;#39;ve both got some interesting strengths&lt;/p&gt;
&lt;p&gt;The first method for multi buffers allow us to do changes that may be more random or complex over multiple files and are great for where interventions are needed due to inconsistencies when doing large refactors&lt;/p&gt;
&lt;p&gt;The second method allows us to automate predictable changes - the goal with this is to minimize the time needed to write a script for manipulating text files, which is often quite time consuming and difficult to understand. In doing so, it should make large changes more efficient and approachable for teams while lowering the barrier to entry overall&lt;/p&gt;
&lt;p&gt;I think there&amp;#39;s also room for composability between these two methods, and possibly even executing a script on a multi buffer using something like &lt;a href=&quot;https://docs.helix-editor.com/commands.html&quot; &gt;Helix&amp;#39;s &lt;code&gt;:pipe&lt;/code&gt; command&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;Okay so sure, we can edit files in some weird ways &amp;quot;fast&amp;quot;. So what?&lt;/p&gt;
&lt;p&gt;My idea here is that this can be a neat way to automate large code changes. Especially if those changes are macro-able. And I think the extension of a general purpose language for working with these kinds of syntax-aware macros can be really powerful. It could also just be a neat find-and-replace tool which is always useful&lt;/p&gt;
&lt;p&gt;Also, it just sounds kind of fun to build and seems like it would fit well into my current text editing workflow. So even if there aren&amp;#39;t any other users there would at least be one - which I think is perfectly fine for small software&lt;/p&gt;
&lt;h2&gt;but but but AI&lt;/h2&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;h2&gt;Update 14 April 2026&lt;/h2&gt;
&lt;p&gt;Just came across &lt;a href=&quot;https://ast-grep.github.io&quot; &gt;ast-grep&lt;/a&gt; which makes it possible to search in an AST aware way which could be very cool&lt;/p&gt;
&lt;h2&gt;Update 15 April 2026&lt;/h2&gt;
&lt;p&gt;Another interesting tool for this kind of text manipulation is &lt;a href=&quot;https://github.com/facebookincubator/fastmod&quot; &gt;fastmod&lt;/a&gt; which allows for regex based replacements in an interactive fashion for manual intervention&lt;/p&gt;
&lt;h2&gt;Update 2 June 2026&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; also has some kind of scripting behavior using &lt;a href=&quot;https://www.gnu.org/software/sed/manual/html_node/sed-script-overview.html&quot; &gt;&lt;code&gt;sed scripts&lt;/code&gt;&lt;/a&gt; but it&amp;#39;s fairly limited and clunky&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Use a password manager, they said</title><link>https://nabeelvalley.co.za/blog/2025/01-10/use-a-password-manager-they-said.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/01-10/use-a-password-manager-they-said.html</guid><description>A rant on how Microsoft is annoying</description><pubDate>Wed, 01 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Use a password manager, they said&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I just had to boot up my computer to download &lt;em&gt;Microsoft Edge&lt;/em&gt; because half way through the day I found out that the &lt;em&gt;Passwords&lt;/em&gt; tab has been removed from the &lt;em&gt;Microsoft Authenticator&lt;/em&gt; app&lt;/p&gt;
&lt;p&gt;A few months ago the app notified me that &lt;em&gt;Autofill&lt;/em&gt; would stop working - I was okay with this, I just started copying and pasting passwords. Next, the ability to add passwords was removed altogether - well okay, I haven&amp;#39;t added a new password in a while so that&amp;#39;s also fine. But then today I see that the passwords tab has been straight up removed&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Turns out that &lt;em&gt;Autofill doesn&amp;#39;t just refer to Autofill. But the entirety of password management&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://support.microsoft.com/en-us/account-billing/changes-to-microsoft-authenticator-autofill-09fd75df-dc04-4477-9619-811510805ab6&quot; &gt;This announcement&lt;/a&gt; outlines the details but I absolutely love the solution&lt;/p&gt;
&lt;p&gt;Basically, you have to download &lt;em&gt;Edge&lt;/em&gt; in order to get passwords to autofill at the OS level. But what if you don&amp;#39;t want to use that but just want your passwords? Well you can still use &lt;em&gt;Edge&lt;/em&gt; since that&amp;#39;s now where passwords live&lt;/p&gt;
&lt;p&gt;Okay. So I downloaded &lt;em&gt;Edge&lt;/em&gt; on my phone (where I was using &lt;em&gt;Authenticator&lt;/em&gt;) with the hope that I&amp;#39;d be able to export my passwords. Nope.&lt;/p&gt;
&lt;p&gt;Get this - since &lt;a href=&quot;https://learn.microsoft.com/en-us/answers/questions/2389677/export-passwords-edge-for-androdi&quot; &gt;the Android app does not support password exporting&lt;/a&gt; you&amp;#39;re going to have to do this on desktop&lt;/p&gt;
&lt;p&gt;So then I downloaded the desktop app, and after installing the malware that is &lt;em&gt;Microsoft Edge&lt;/em&gt; on my computer, I can now export my passwords.&lt;/p&gt;
&lt;p&gt;Okay. Got the passwords. All good.&lt;/p&gt;
&lt;p&gt;Technically, yes. But my issue here isn&amp;#39;t just technical.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s first address my reason for using &lt;em&gt;Authenticator&lt;/em&gt;. So when 2FA was becoming a thing, companies wanted you to have it. At some point, I had to install it so that corporate 2FA would work. And, well, I wasn&amp;#39;t going to use multiple 2FA apps - and to be completely honest, I was just a lot less critical of the companies making some of these tools at the time&lt;/p&gt;
&lt;p&gt;So anyways, that&amp;#39;s how everything got in there to begin with&lt;/p&gt;
&lt;p&gt;Well, my browser is where I&amp;#39;m drawing the line. It&amp;#39;s one thing to copy and paste passwords out of an app, it&amp;#39;s something else for most of my online interactions to go through the giant data collection service that is &lt;em&gt;Edge&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The concern I share is broader though. I&amp;#39;m technical enough to find the documentation and get my data migrated over. But what if you don&amp;#39;t know how do do all that export/import jazz, or you don&amp;#39;t even have a desktop. What if you don&amp;#39;t really understand the implications of having a single organization tracking you across all your interactions&lt;/p&gt;
&lt;p&gt;It&amp;#39;s as simple as pushing you towards a specific web browser, or search engine, or forcing you to log into &lt;em&gt;Windows&lt;/em&gt; with your &lt;em&gt;Microsoft Account&lt;/em&gt; - because that&amp;#39;s the only way to use the computer that you own&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s also not forget about &lt;a href=&quot;https://www.bbc.com/news/articles/cpwwqp6nx14o&quot; &gt;&lt;em&gt;Copilot&lt;/em&gt; that was recording every action users did&lt;/a&gt; along with literal screenshots&lt;/p&gt;
&lt;p&gt;Passwords are pretty important these days. It kind of sucks that big organizations are continuously pulling us into these closed systems that become harder to escape at every step. I struggle to suggest a good solution at this point other that just finding another password manager that&amp;#39;s not controlled by a big corp - or well, write all your passwords on a piece of paper I guess&lt;/p&gt;
&lt;p&gt;There are also some other solutions like &lt;a href=&quot;https://en.wikipedia.org/wiki/YubiKey&quot; &gt;Yubikeys&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/WebAuthn&quot; &gt;WebAuthn&lt;/a&gt; or other &lt;a href=&quot;https://en.wikipedia.org/wiki/FIDO_Alliance&quot; &gt;FIDO stuff&lt;/a&gt; but they&amp;#39;re going to be hit or miss depending on what services or devices you&amp;#39;re accessing and I don&amp;#39;t really know what support for these kinds of technologies is like so I don&amp;#39;t think a 100% migration is even really possible&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Patching packages with PNPM</title><link>https://nabeelvalley.co.za/blog/2025/03-07/pnpm-package-patch.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/03-07/pnpm-package-patch.html</guid><description>Using PNPM&#39;s patching commands to modify installed dependencies</description><pubDate>Thu, 03 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Patching packages with PNPM&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Patching packages is a task that&amp;#39;s occasionally done to fix bugs or update behavior of 3rd party dependencies within a specific project. This is often done while waiting for a fix from the upstream library or when the library author does not agree with the change that is needed&lt;/p&gt;
&lt;h2&gt;Creating a Patch&lt;/h2&gt;
&lt;p&gt;Say we have some package installed that we&amp;#39;d like to patch, for example we&amp;#39;ll call this &lt;code&gt;my-package&lt;/code&gt;. We currently have &lt;code&gt;my-package&lt;/code&gt; version &lt;code&gt;1.1.1&lt;/code&gt; installed and want to create a patch for that. We can kick this process off with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; patch&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-package@1.1.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Doing this will result in some output from &lt;code&gt;pnpm&lt;/code&gt; with a path to a directory that contains the package&amp;#39;s code that we can modify&lt;/p&gt;
&lt;p&gt;To modify the code, open the given path in your editor and make the required changes&lt;/p&gt;
&lt;p&gt;Once you&amp;#39;re satisfied with the changes, you can use the following command to commit the patch:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; patch-commit&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; path/to/folder&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;patches/my-package@1.1.1.patch&lt;/code&gt; file with the patch&lt;/li&gt;
&lt;li&gt;Add a reference to this patch in the &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Install dependencies and apply this patch&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The patch will be applied in future whenever dependencies are installed/added&lt;/p&gt;
&lt;h2&gt;Removing a Patch&lt;/h2&gt;
&lt;p&gt;To remove a patch you can use the &lt;code&gt;pnpm patch-remove&lt;/code&gt; command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;pnpm&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; patch-remove&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-package@1.1.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;That will remove the patch from the &lt;code&gt;patches&lt;/code&gt; directory as well as from the &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; file&lt;/p&gt;
&lt;h2&gt;Updating a Patch&lt;/h2&gt;
&lt;p&gt;To update a patch you will need to remove it and then re-create it using the info above&lt;/p&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;p&gt;Patching is annoying, avoid it if you can&lt;/p&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;PNPM has documentation for all of the above mentioned commands on the &lt;a href=&quot;https://pnpm.io/cli/patch&quot; &gt;Patching Dependencies Docs&lt;/a&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Snippet: Rachets, not Levers - Chris Krycho</title><link>https://nabeelvalley.co.za/blog/2025/03-11/rachets-not-levers.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/03-11/rachets-not-levers.html</guid><description>Quote from Chris Krycho</description><pubDate>Mon, 03 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Snippet: Rachets, not Levers - Chris Krycho&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I came across this quote on &lt;a href=&quot;https://v5.chriskrycho.com/cv/#philosophy-ratchets-not-levers&quot; &gt;Chris Krycho&amp;#39;s Website&lt;/a&gt; that I thought was worth sharing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;The real wins, then, are tools which do not require everyone to be at their best at every moment: ratchets, not levers. Levers let you move things, but if you are holding something up with a lever, you have to keep holding it — forever. A ratchet lets you drive forward motion without slipping back as soon as you let up on the pressure.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Web Workers and Vite</title><link>https://nabeelvalley.co.za/blog/2025/06-01/web-workers.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/06-01/web-workers.html</guid><description>An overview of using Web Workers with Vite</description><pubDate>Mon, 06 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Web Workers and Vite&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Web workers provide a mechanism for running code outside of the main thread using Javascript. They are currently supported in the browser as well as in Node.js, but for the purpose of this post we&amp;#39;ll look at how to use them from within the browser&lt;/p&gt;
&lt;h2&gt;Vanilla&lt;/h2&gt;
&lt;p&gt;Web workers can be used directly from the browser using some script tags. For the sake of example, we&amp;#39;ll use the following HTML file with it&amp;#39;s related script tags:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/index.html&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; html&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;html&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; lang&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; charset&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; http-equiv&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;X-UA-Compatible&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;IE=edge&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;meta&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;viewport&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Web Workers&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;title&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- script for launching web workers --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;module&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./worker-launcher.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    &amp;lt;!-- script to register service worker --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;module&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./register-service-worker.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;head&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;body&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Images that will br proxied to Service Worker&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;placeholder?height=400&amp;amp;width=500&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;img&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;placeholder?height=200&amp;amp;width=500&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;body&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;html&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;In the above, we can see three scripts referenced, we&amp;#39;ll take a look at these as we talk about the mechanisms for using web workers&lt;/p&gt;
&lt;h3&gt;Workers&lt;/h3&gt;
&lt;p&gt;Web workers are simply Javascript modules that are loaded by some other code dynamically as a &lt;code&gt;Worker&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If we assume we have some worker called &lt;code&gt;simple-worker.js&lt;/code&gt; in the same directory of our page, we can load it using the following code:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Worker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./simple-worker.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Upon doing this, the &lt;code&gt;simple-worker.js&lt;/code&gt; script will be loaded and executed. &lt;/p&gt;
&lt;p&gt;Now, the real value of workers comes from the ability to get data from the code that launches it, this is done using &lt;code&gt;worker.postMessage&lt;/code&gt;, this allows us to send any data we want to the worker we have defined, so we can do this in our script, an example of this can be seen below:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/simple-worker-launcher.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Worker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./simple-worker.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ worker });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello there&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setTimeout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;terminate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello again&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;On the other side of this conversation we have the actual worker script/module. This actually looks really simple:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/simple-worker.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;launched simple worker&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;got event&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, e.data));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;This file uses &lt;code&gt;self.addEventListener&lt;/code&gt; to listen to &lt;code&gt;messsage&lt;/code&gt;s sent to the worker, when a message is received, the worker can decide what to do with it - what&amp;#39;s important to know is that this handler does not block the main thread so it can be as intensive as we want&lt;/p&gt;
&lt;p&gt;The worker can also be more complex, for example we can see in the below message that the worker receives a message via &lt;code&gt;self.addEventListener&lt;/code&gt;, after doing some intensive processing, it calls &lt;code&gt;self.postMessage&lt;/code&gt; to basically respond to the parent&lt;/p&gt;
&lt;p&gt;The parent can then listen to these messages with &lt;code&gt;worker.addEventListener&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/worker-launcher.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Worker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./worker.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ worker });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello there&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message from worker&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, e.data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;And we can see the worker that sends messages as well:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/worker.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// in the worker state `self` is an instance of `DedicatedWorkerGlobalScope` which is like `window`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// `window` is also not defined in this scope&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ self, typeofWindow: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; window });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doIntensiveThing&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;started intensive thing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; start&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; end&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; start &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 3000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do nothing, just block the tread for 10 seconds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  while&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (Date.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;now&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; end) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// some events we can also listen for are on the `self` object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ev&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // messages passed from the service worker will arrive here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ dataToWorker: ev.data });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // if the message is the word `slow` then we will do some intensive thing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (ev.data &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;slow&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;start processing slow thing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    doIntensiveThing&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;done processing slow thing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;else&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;done processing fast thing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h3&gt;ServiceWorkers&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ServiceWorkers&lt;/code&gt; are a special kind of worker that acts as a proxy between the application and network and can interact with network requests even when the device is not connected to the server&lt;/p&gt;
&lt;p&gt;Service workers have different events that may be triggered, commonly is the &lt;code&gt;installed&lt;/code&gt;, &lt;code&gt;activated&lt;/code&gt;, and &lt;code&gt;fetch&lt;/code&gt; event among others, we add listners for these events the same as we did in the above&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/service-worker.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;install&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;installed&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;activate&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;activated&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;self.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;fetch&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;event&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event.request.url);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (event.request.url.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;includes&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;placeholder&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; URL&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(event.request.url);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; url.searchParams.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;height&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 200&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; url.searchParams.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;width&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;||&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 500&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;image requested&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    event.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;respondWith&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      fetch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;        `https://placehold.co/${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}x${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;width&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}?text=This image does not exist`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;In the above file, we intercept requests to the &lt;code&gt;placeholder&lt;/code&gt; url and proxy it by making a new request to &lt;code&gt;https://placeholder.co&lt;/code&gt;, we could do anything here though, even responding with our own data if we want&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ServiceWorkers&lt;/code&gt; are special though since an application can only have a single &lt;code&gt;ServiceWorker&lt;/code&gt;. Creating a &lt;code&gt;ServiceWorker&lt;/code&gt; is done using &lt;code&gt;navigator.serviceWorker.register&lt;/code&gt; and not using &lt;code&gt;new Worker&lt;/code&gt;, an example of service worker registration can be seen below:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/plain/register-service-worker.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;navigator.serviceWorker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;register&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;service-worker.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;then&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;registered service worker&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h2&gt;Vite&lt;/h2&gt;
&lt;p&gt;In practice we&amp;#39;re rarely using some random Javascript files though and often have more complex scenarios with external dependencies or even stuff like Typescript involved, in this case we need to consider things like bundling as well as somehow resolving the name of the file we need to load. Thankfully modern bundlers like Vite have a solution for us&lt;/p&gt;
&lt;p&gt;In the case of Vite specifically, it provides us with an API that we can use while importing files that Vite uses to infer that a file should be treated as a worker. Vite does this by using the &lt;code&gt;?worker&lt;/code&gt; at the end of the import path&lt;/p&gt;
&lt;p&gt;Assume we have some Vite-based project that uses a worker such as the one below. That worker also imports some code from another file we have and we expect it all to be bundled correctly:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/vite/src/canvas.worker.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { animate } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;./canvas&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; InvokeParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  canvas&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; OffscreenCanvas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// setup if in worker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(e.data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; InvokeParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  animate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(canvas)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;We can see that we have a &lt;code&gt;run&lt;/code&gt; function that is called when we receive the &lt;code&gt;message&lt;/code&gt; as before, we also have a type specified for the data we expect to receive&lt;/p&gt;
&lt;p&gt;When we import something using &lt;code&gt;?worker&lt;/code&gt; Vite creates a constructor for us that will initialize the worker without us having to manually pass the path to the file, so a consumer of this file can now use the worker a bit like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; CanvasWorker &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./canvas.worker?worker&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { InvokeParams } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./canvas.worker&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; CanvasWorker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ canvas: offscreen } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;satisfies&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; InvokeParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, [offscreen])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Note that we also use the &lt;code&gt;type&lt;/code&gt; import above so we can keep the type definition of the data our worker expects in the same palce as the worker&lt;/p&gt;
&lt;p&gt;A more full example of this can be seen below:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;web-workers/vite/src/canvas.worker.ts&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { animate } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;./canvas&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; InvokeParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  canvas&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; OffscreenCanvas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// setup if in worker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(e.data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; InvokeParams&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  animate&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(canvas)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;p&gt;Something that&amp;#39;s also interesting to note is the second parameter of &lt;code&gt;postMessage&lt;/code&gt;, this is an array of &lt;code&gt;TransferrableObjects&lt;/code&gt; that are specific objects that the browser allows us to share between the main thread and worker threads. In the above example we&amp;#39;re using a &lt;code&gt;OffscreenCanvas&lt;/code&gt; but this can be any of the objects that are defined as &lt;code&gt;TransferrableObjects&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall, web workers are pretty fun to play around with and really increase the options available to us when working to make applications more performant. Modern tools like Vite also make using them pretty easy&lt;/p&gt;
&lt;p&gt;There&amp;#39;s a lot that you can do with workers and I&amp;#39;ve simply provided you with a small overview of the functionality, looking at the MDN documentation is always a good place to go to learn more&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API&quot; &gt;MDN Web Workers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API&quot; &gt;MDN Service Workers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://v3.vitejs.dev/guide/features.html#web-workers&quot; &gt;Web Workers in Vite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/articles/offscreen-canvas&quot; &gt;Speed up Canvas Operations with OffscreenCanvas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Accessibility Reference List</title><link>https://nabeelvalley.co.za/blog/2025/07-07/accessibility-tools.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/07-07/accessibility-tools.html</guid><description>A collection of useful accessibility tools and resources</description><pubDate>Mon, 07 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Accessibility Reference List&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;Some websites or content that cover accessibility topics&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/WCAG21/&quot; &gt;Web Content Accessibility Guidelines (WCAG)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sarasoueidan.com/&quot; &gt;Sara Soueidan&amp;#39;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://adrianroselli.com/&quot; &gt;Adrian Roselli&amp;#39;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hidde.blog/&quot; &gt;Hidde&amp;#39;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Courses&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/courses/foundations-course/&quot; &gt;WCAG Digital Accessibility Foundations&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Bookmarklets&lt;/h2&gt;
&lt;p&gt;Bookmarklets that make checking accessibility easier&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;IDK how to save a bookmarklet, look at your browser&amp;#39;s documentation I guess&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://hinderlingvolkart.github.io/h123&quot; &gt;H123 Accessibility Outliner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://accessibility-bookmarklets.org/install.html&quot; &gt;Layout Related Accessibility Bookmarklets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Week 36, Creativity</title><link>https://nabeelvalley.co.za/blog/2025/07-09/week-36-creativity.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/07-09/week-36-creativity.html</guid><description>Creative software and generative art</description><pubDate>Sun, 07 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Week 36, Creativity&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I&amp;#39;ve kind of always wondered how people make those crazy art installations with loads of lights and stuff, turns out there&amp;#39;s software that exists for that&lt;/p&gt;
&lt;h2&gt;What I Found&lt;/h2&gt;
&lt;p&gt;Relatively obscure but here are a couple of generative art tools, one for music and one for everything?? They&amp;#39;re both kinda fascinating, you should take a look&lt;/p&gt;
&lt;h3&gt;Strudel&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://strudel.cc/&quot; &gt;Strudel&lt;/a&gt; is an a programming based music performing software that also looks super sick&lt;/p&gt;
&lt;h3&gt;TouchDesigner&lt;/h3&gt;
&lt;p&gt;While diving into some art on the internet this name kept coming up. &lt;a href=&quot;https://derivative.ca/&quot; &gt;TouchDesigner&lt;/a&gt; is a node based application for creating generative art and art installations that work with loads of different input and output types&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Coat Rack</title><link>https://nabeelvalley.co.za/blog/2025/09-11/coat-rack.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/09-11/coat-rack.html</guid><description>A cloud for people who don&#39;t like clouds</description><pubDate>Sun, 09 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Coat Rack&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Coat Rack is a platform that provides users with the necessary tools to own and share their data within their physical space. Enabling non-technical users to take control of their data ownership is the foundation on which the platform is built.&lt;/p&gt;
&lt;p&gt;This enables users to take their daily utilities off the cloud and move their data to something they own while providing a user experience that is on par with that of cloud-based applications.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve been working on the project with &lt;a href=&quot;https://ldam.co.za/about&quot; &gt;Logan Dam&lt;/a&gt; since early 2024. I recently gave a presentation on the project and though this may be a good time to mention it on my site as well. You can also find the &lt;a href=&quot;https://github.com/coat-rack/app&quot; &gt;coat-rack repo on GitHub&lt;/a&gt; if you&amp;#39;d like to contribute or just browse&lt;/p&gt;
&lt;embed type=&quot;application/pdf&quot; src=&quot;/content/projects/coat-rack-presentation.pdf#zoom=FitH&quot; style=&quot;width: 100%; aspect-ratio: 3/2;&quot; &gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Shader Web Component</title><link>https://nabeelvalley.co.za/blog/2025/09-11/shader-web-component.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/09-11/shader-web-component.html</guid><description>Example of a web component for rendering Web GPU Shaders</description><pubDate>Sun, 09 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Shader Web Component&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;So I want to use some more shaders and I want to also migrate everything over to use &lt;code&gt;wgsl&lt;/code&gt; instead of &lt;code&gt;glsl&lt;/code&gt; but it&amp;#39;s kinda annoying to set them up every time so I made a little web component for using them, this is very much a work-in-progress, but here&amp;#39;s it in action:&lt;/p&gt;
&lt;site-shader-canvas&gt;
  &lt;canvas width=&quot;1000&quot; height=&quot;500&quot; style=&quot;width: 100%&quot; &gt;&lt;/canvas&gt;
  &lt;script type=&quot;text/wgsl&quot; path=&quot;./shader.wgsl&quot; &gt;struct VertexOutput {
  @builtin(position) position: vec4f,
  @location(0) texcoord: vec2f,
};

@vertex fn vs(
  @builtin(vertex_index) vertexIndex : u32
) -&gt; VertexOutput {
  const pos = array(
    vec2( 1.0,  1.0),
    vec2( 1.0, -1.0),
    vec2(-1.0, -1.0),
    vec2( 1.0,  1.0),
    vec2(-1.0, -1.0),
    vec2(-1.0,  1.0),
  );

  var vsOutput: VertexOutput;

  let xy = pos[vertexIndex];
  vsOutput.texcoord = pos[vertexIndex] * vec2f(0.5, 0.5) + vec2f(0.5);
  vsOutput.position = vec4f(pos[vertexIndex], 0, 1);

  return vsOutput;
}

@group(1) @binding(0) var&lt;uniform&gt; uTime: f32;

@fragment fn fs(fsInput: VertexOutput) -&gt; @location(0) vec4f {
  var red = abs(sin(uTime/10.0)) * fsInput.texcoord.x;
  var blue = abs(cos(uTime/5.0)) * fsInput.texcoord.y;
  return vec4f(red, 0.0, blue, 1.0);
}
&lt;/script&gt;
&lt;/site-shader-canvas&gt;&lt;p&gt;Using the component looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;module&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; src&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/web-components/shader-canvas.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;site-shader-canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;canvas&lt;/span&gt;&lt;span style=&quot;color:#6E011A;--shiki-light-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic&quot; &gt; /&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;text/wgsl&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    struct VertexOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      @builtin(position) position: vec4f,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      @location(0) texcoord: vec2f,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @vertex fn vs(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      @builtin(vertex_index) vertexIndex : u32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ) -&amp;gt; VertexOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      const pos = array(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2( 1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2( 1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2(-1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2( 1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2(-1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2(-1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var vsOutput: VertexOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      let xy = pos[vertexIndex];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      vsOutput.texcoord = pos[vertexIndex] * vec2f(0.5, 0.5) + vec2f(0.5);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      vsOutput.position = vec4f(pos[vertexIndex], 0, 1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      return vsOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @group(0) @binding(0) var&amp;lt;uniform&amp;gt; uTime: f32;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @fragment fn fs(fsInput: VertexOutput) -&amp;gt; @location(0) vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var red = abs(sin(uTime/10.0)) * fsInput.texcoord.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var blue = abs(cos(uTime/5.0)) * fsInput.texcoord.y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      return vec4f(red, 0.0, blue, 1.0);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;site-shader-canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The component code is:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// @ts-check&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { setupCanvas } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./shader.js&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; ShaderCanvas&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; extends&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; HTMLElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; observedAttributes&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;centered&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;highlight&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;large&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /** &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {MutationObserver}&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  #observer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /** &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {HTMLCanvasElement}&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  #canvas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /** &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {HTMLScriptElement}&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  #script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  constructor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    super&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#observer &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; MutationObserver&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;#initialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#observer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;observe&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, { childList: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  disconnectedCallback&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#observer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;disconnect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  connectedCallback&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;#initialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; #&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;initialize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;here&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; initialized&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#canvas &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (initialized) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; canvas&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;canvas&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    /** &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {HTMLScriptElement}&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; script&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;script[type=&amp;quot;text/wgsl&amp;quot;]&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(script &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; canvas)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#observer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;disconnect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#canvas &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; canvas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#script &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(canvas, script)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; render&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setupCanvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#canvas, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;this&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.#script.innerText)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; renderLoop&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      requestAnimationFrame&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;?.()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;        renderLoop&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    renderLoop&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;customElements.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;define&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;site-shader-canvas&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, ShaderCanvas)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the code for actually doing the shader rendering pipeline is and is a heavily simplified version of what I&amp;#39;m currently using for my &lt;a href=&quot;/blog/2024/24-08/unintentionally-made-a-programming-language&quot; &gt;Image Editor&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// @ts-check&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {HTMLCanvasElement}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; canvas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {string}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; shader&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; - WebGPU Shader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@returns&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {Promise&amp;lt;((saveTo?: string) =&amp;gt; void) | undefined&amp;gt;}&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; renderer function. Will be `undefined` if there is an instantiation error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setupCanvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  shader&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // @ts-ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; adapter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; navigator.gpu?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;requestAdapter&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; device&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; adapter?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;requestDevice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;device) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {any}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ctx&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; canvas?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getContext&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;webgpu&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;ctx) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // @ts-ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; format&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; navigator.gpu.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getPreferredCanvasFormat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ctx.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;configure&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    device,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    format,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; module&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createShaderModule&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    label: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;base shader&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    code: shader,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pipeline&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createRenderPipeline&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    label: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;render pipeline&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    layout: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;auto&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    vertex: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      module,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    fragment: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      module,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      targets: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          format,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; uTime&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createBuffer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    size: [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // @ts-ignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    usage: GPUBufferUsage.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;UNIFORM&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; GPUBufferUsage.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;COPY_DST&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; curr &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {string}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [saveTo]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; render&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;saveTo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    curr &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // https://stackoverflow.com/questions/70284258/destroyed-texture-texture-used-in-a-submit-when-using-a-video-texture-in-ch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // render pass descriptor needs to be recreated since this doesn&amp;#39;t live very long on the GPU&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; renderPassDescriptor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      label: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;render pass descriptor&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      colorAttachments: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          loadOp: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;clear&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          storeOp: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          clearValue: [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          view: ctx.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getCurrentTexture&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createView&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; bindGroup&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createBindGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      layout: pipeline.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;getBindGroupLayout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      entries: [{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        binding: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        resource: { buffer: uTime }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; encoder&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; device.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createCommandEncoder&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ label: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;command encoder&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; pass&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; encoder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;beginRenderPass&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(renderPassDescriptor)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    pass.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setPipeline&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(pipeline)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    pass.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setBindGroup&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, bindGroup)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    device.queue.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;writeBuffer&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(uTime, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Float32Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([curr]));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    pass.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;draw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;6&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// call our vertex shader 6 times&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    pass.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;end&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; commandBuffer&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; encoder.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;finish&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    device.queue.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;submit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([commandBuffer])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (saveTo) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // saving must be done during the render&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      downloadCanvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(canvas, saveTo)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; render&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {HTMLCanvasElement}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; canvas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; * &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@param&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; {string}&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; downloadCanvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; canvas.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toDataURL&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;image/png&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; link&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  link.download &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; name.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;split&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;slice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;).&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;join&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;.png&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  link.href &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  link.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;click&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  link.parentNode?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;removeChild&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(link)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Exploring the CSS Paint API</title><link>https://nabeelvalley.co.za/blog/2025/10-07/css-houdini-paint-api.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/10-07/css-houdini-paint-api.html</guid><description>Walking through a simple example of using the CSS Houdini Paint API</description><pubDate>Thu, 10 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Exploring the CSS Paint API&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/CSS_Painting_API&quot; &gt;The CSS Painting API&lt;/a&gt; is part of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/CSS_Painting_API&quot; &gt;the CSS Houdini group of APIs&lt;/a&gt; which provide low level access to the CSS engine&lt;/p&gt;
&lt;p&gt;The CSS Houdini APIs use the idea of &amp;quot;worklets&amp;quot; which are basically JS files that the CSS engine will use as part of it&amp;#39;s rendering pipeline&lt;/p&gt;
&lt;p&gt;For the sake of this example, I&amp;#39;ll be looking specifically at the CSS Painting API to build a custom CSS &lt;code&gt;paint&lt;/code&gt; worklet&lt;/p&gt;
&lt;h2&gt;The CSS &lt;code&gt;paint&lt;/code&gt; function&lt;/h2&gt;
&lt;p&gt;Before getting into specifics around how to implement a worklet, it&amp;#39;s nice to see what we&amp;#39;re trying to get to. Worklets are effectively JS functions that we can &amp;quot;call&amp;quot; from our CSS code to modify how an element is rendered. The CSS Painting API exposes a &lt;code&gt;paint&lt;/code&gt; function in CSS. Let&amp;#39;s assume we have a worklet called &lt;code&gt;myCustomPainter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We would be able to apply this to some &lt;code&gt;html&lt;/code&gt; code like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;fancy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello world&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can style this using the CSS &lt;code&gt;paint&lt;/code&gt; function with the name of our worklet:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.fancy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-image&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: paint(myCustomPainter);  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will invoke our worklet to &lt;code&gt;paint&lt;/code&gt; a custom background for our element&lt;/p&gt;
&lt;h2&gt;The Methods Available&lt;/h2&gt;
&lt;p&gt;The CSS Paint API exposes a few different methods and bits of functionality to us&lt;/p&gt;
&lt;p&gt;Firstly, we have the methods needed for defining a worklet, this is the global &lt;code&gt;CSS.paintWorklet.addModule&lt;/code&gt; method:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; paintWorklet&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    addModule&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, we also have the &lt;code&gt;registerPaint&lt;/code&gt; function which is a global function in the Worklet scope that is used to register a class that handles painting:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;paintCtor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterOptions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The actual &lt;code&gt;PainterOptions&lt;/code&gt; consists of two parts, a &lt;code&gt;Paint&lt;/code&gt; class that handles the actual painting, and a static &lt;code&gt;PainterClassRef&lt;/code&gt; that specificies some metadata about the &lt;code&gt;Paint&lt;/code&gt; class:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintRenderingContext&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;size&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintSize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;styleMap&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StylePropertyMapReadOnly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintCtor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Paint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterClassRef&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * CSS Properties accessed by the `paint` function. These can be normal or custom properties.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  inputProperties&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Specififes if the rendering context supports transparency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  contextOptions&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;alpha&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Inputs to the `paint` function from CSS.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Not supported in any browsers I&amp;#39;ve tested.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Chrome on MacOS will completely break rendering the `paint` function is passed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * any values in the CSS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  inputArguments&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterOptions&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterClassRef&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintCtor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Lastly, for the sake of completeness, the remaining types used by the above definitions are:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/** Not exactly a Canvas but it&amp;#39;s pretty similar */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintRenderingContext&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CanvasRenderingContext2D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintSize&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Defining a Worklet&lt;/h2&gt;
&lt;p&gt;A simple Paint class without any input properties looks something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyCustomPainter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; implements&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; contextOptions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { alpha: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;myCustomPainter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, MyCustomPainter);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintRenderingContext&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;_size&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintSize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;styleMap&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StylePropertyMapReadOnly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) { }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;registerPaint&lt;/code&gt; method isn&amp;#39;t strictly necessary but it lets us keep the registration inside of the class which is nice&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Registering this as a worklet is done in two steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;From our main script, we need to run &lt;code&gt;CSS.paintWorklet.addModule&lt;/code&gt;. I&amp;#39;m using the Vite &lt;code&gt;url&lt;/code&gt; param to get this directly from the path to my worklet file:&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; workletUrl &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./worklet?url&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.paintWorklet.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addModule&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(workletUrl)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol start=&quot;2&quot; &gt;
&lt;li&gt;From the worklet, you need to register the &lt;code&gt;MyCustomPainter&lt;/code&gt; as a &lt;code&gt;painter&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { MyCustomPainter } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;./my-painter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;MyCustomPainter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Taking Inputs&lt;/h2&gt;
&lt;p&gt;In order for our worklet to do something fun we will probably want to take some inputs. We can specifiy which CSS properties (or custom properties) we want to use as an input - we do this via &lt;code&gt;inputProperties&lt;/code&gt;. We can also register a custom property by using &lt;code&gt;CSS.registerProperty&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For our example, we&amp;#39;ll also define a method in the &lt;code&gt;MyCustomPainter&lt;/code&gt; class that does this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ... rest of class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;static readonly colorProp &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;--custom-painter-color&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;static &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    name: MyCustomPainter.colorProp,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    syntax: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&amp;lt;color&amp;gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    inherits: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    initialValue: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;transparent&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;static get &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;inputProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [MyCustomPainter.colorProp]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ... rest of class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then, we need to call the &lt;code&gt;registerProperties&lt;/code&gt; method above to register the custom property in the &lt;code&gt;main.ts&lt;/code&gt; file (or somewhere in the normal page/JS context)&lt;/p&gt;
&lt;p&gt;We can do this along with where we defined the worklet:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { MyCustomPainter } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./my-painter&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; workletUrl &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./worklet?url&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.paintWorklet.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addModule&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(workletUrl)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;MyCustomPainter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;While it should be possible to get inputs as &lt;code&gt;arguments&lt;/code&gt; to a painter, it seems that is not supported on any browsers as yet&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This will make it so that we can provide inputs when painting. Inputs can come from our CSS, so using our worklet now looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.fancy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  --custom-painter-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;yellow&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-image&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: paint(myCustomPainter);  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then, we can access this in the &lt;code&gt;paint&lt;/code&gt; method to do something like draw a rectangle over the entire canvas&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// ... rest of class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ctx: PaintRenderingContext, size: PaintSize, styleMap: StylePropertyMapReadOnly) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; color&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; styleMap.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(MyCustomPainter.colorProp)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ctx.fillStyle &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; color&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ctx.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;fillRect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, size.width, size.height)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;paint&lt;/code&gt; method receives a rendering &lt;code&gt;context&lt;/code&gt;, the &lt;code&gt;size&lt;/code&gt; of the element, and the &lt;code&gt;styles&lt;/code&gt; that we defined in &lt;code&gt;registerProperties&lt;/code&gt; (if they are set on the element)&lt;/p&gt;
&lt;p&gt;It&amp;#39;s also nice to note that since we&amp;#39;ve specified that &lt;code&gt;--custom-painter-color&lt;/code&gt; has an &lt;code&gt;initialValue&lt;/code&gt; it will not be &lt;code&gt;undefined&lt;/code&gt; and the browser will provide us with the &lt;code&gt;initialValue&lt;/code&gt; if it&amp;#39;s not provided&lt;/p&gt;
&lt;p&gt;And that&amp;#39;s really about it. The API is pretty simple but powerful and makes it possible to do so much&lt;/p&gt;
&lt;h2&gt;The Complete Worklet&lt;/h2&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;fancy&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello world&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.fancy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  --custom-painter-color&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;yellow&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  background-image&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: paint(myCustomPainter);  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; MyCustomPainter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; implements&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; colorProp&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;--custom-painter-color&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; registerProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerProperty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      name: MyCustomPainter.colorProp,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      syntax: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&amp;lt;color&amp;gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      inherits: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      initialValue: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;transparent&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;myCustomPainter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, MyCustomPainter);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; inputProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [MyCustomPainter.colorProp]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  static&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; get&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; contextOptions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { alpha: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintRenderingContext&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;size&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintSize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;styleMap&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StylePropertyMapReadOnly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; color&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; styleMap.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(MyCustomPainter.colorProp)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ctx.fillStyle &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; color&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ctx.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;fillRect&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, size.width, size.height)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { MyCustomPainter } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;./my-painter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;MyCustomPainter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { MyCustomPainter } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./my-painter&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; workletUrl &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;./worklet?url&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;MyCustomPainter.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;registerProperties&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.paintWorklet.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addModule&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(workletUrl)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Types for working with the CSS Paint API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;namespace&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CSS&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; paintWorklet&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    addModule&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;url&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; registerPaint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;paintCtor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterOptions&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  paint&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ctx&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintRenderingContext&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;size&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintSize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;styleMap&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; StylePropertyMapReadOnly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintCtor&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Paint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; interface&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterClassRef&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  inputProperties&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  contextOptions&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;alpha&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  /**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Not supported in any browsers I&amp;#39;ve tested.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * Chrome on MacOS will completely break rendering the `paint` function is passed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   * any values in the CSS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;   */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  inputArguments&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;?:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterOptions&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PainterClassRef&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintCtor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintRenderingContext&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; CanvasRenderingContext2D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;declare&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; PaintSize&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;height&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;width&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;There are loads of things you can do with the Houdini APIs, some things I recommend reading and taking a look at on this topic are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/css-paint-api-1/&quot; &gt;The CSS Paint API Spec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ishoudinireadyyet.com/&quot; &gt;Is Houdini Ready Yet?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-houdini.iamvdo.me/&quot; &gt;CSS Houdini Experiments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_properties_and_values_API/Houdini&quot; &gt;MDN CSS Houdini Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;p&gt;It&amp;#39;s kinda annoying how many moving parts this has and that makes it a little challenging to include a live example on this blog. Hopefully the other examples I&amp;#39;ve linked above will serve this purpose&lt;/p&gt;
&lt;p&gt;Some nice next things to look at from here are the other Houdini APIs since they offer very different sets of functionality and can be combined to do some interesting stuff&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Côte d&#39;Azur</title><link>https://nabeelvalley.co.za/blog/2025/10-09/cote-d-azure.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/10-09/cote-d-azure.html</guid><description>Some photos from the South of France</description><pubDate>Wed, 10 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Côte d&amp;#39;Azur&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Nice, France&lt;/h2&gt;
&lt;p&gt;We spent some time in the South of France recently.
The weather for the entire trip was pretty fabulous, warm, sunny, beachy days.
Most of our trip was spent in Nice where we stayed right on the border of the old city, filled with lovely markets and great food.
The short walk up to the waterfall - Cascade du Château - was also fantastic and had a wonderful view of the coastline&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Chairs-and-tables-outside.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Chairs and tables outside&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Chairs%20and%20tables%20outside.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Flags-along-promanade.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Flags along promanade&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Flags%20along%20promanade.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Mountain-between-pink-and-orange-buildings.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Mountain between pink and orange buildings&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Mountain%20between%20pink%20and%20orange%20buildings.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Painter-standing-on-window-ledge.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Painter standing on window ledge&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Painter%20standing%20on%20window%20ledge.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Person-putting-on-scooter-helmet.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Person putting on scooter helmet&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Person%20putting%20on%20scooter%20helmet.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Road-with-buildings-along-it.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Road with buildings along it&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Road%20with%20buildings%20along%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Rocks-in-sea.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Rocks in sea&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Rocks%20in%20sea.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Rocks-on-seaside.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Rocks on seaside&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Rocks%20on%20seaside.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Tree-in-front-of-building.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Tree in front of building&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Tree%20in%20front%20of%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Tree-sticking-out-of-gap-between-umbrellas.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Tree sticking out of gap between umbrellas&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Tree%20sticking%20out%20of%20gap%20between%20umbrellas.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt15-45---color---FR---Nice---Tree-with-pink-flowers.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Tree with pink flowers&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Tree%20with%20pink%20flowers.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt75-300---color---FR---Nice---Balconies-in-the-sun.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt75-300 - color - FR - Nice - Balconies in the sun&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Balconies%20in%20the%20sun.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt75-300---color---FR---Nice---Long-palm-tree.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt75-300 - color - FR - Nice - Long palm tree&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Long%20palm%20tree.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-06---xt75-300---color---FR---Nice---Mountains-in-the-distance.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt75-300 - color - FR - Nice - Mountains in the distance&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-06%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Mountains%20in%20the%20distance.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt15-45---color---FR---Nice---Beach.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-07 - xt15-45 - color - FR - Nice - Beach&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Beach.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt75-300---color---FR---Nice---Beach-umbrellas.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-07 - xt75-300 - color - FR - Nice - Beach umbrellas&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Beach%20umbrellas.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt75-300---color---FR---Nice---Corner-of-shiny-building.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-07 - xt75-300 - color - FR - Nice - Corner of shiny building&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Corner%20of%20shiny%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt75-300---color---FR---Nice---People-standing-at-beach-between-umbrellas.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-07 - xt75-300 - color - FR - Nice - People standing at beach between umbrellas&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20People%20standing%20at%20beach%20between%20umbrellas.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt75-300---color---FR---Nice---Person-in-water-with-plane-flying-in-the-distance.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-07 - xt75-300 - color - FR - Nice - Person in water with plane flying in the distance&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Person%20in%20water%20with%20plane%20flying%20in%20the%20distance.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt75-300---color---FR---Nice---Person-sitting-at-restuarant.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-07 - xt75-300 - color - FR - Nice - Person sitting at restuarant&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Person%20sitting%20at%20restuarant.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-07---xt75-300---color---FR---Nice---Person-with-hat-in-the-water.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-07 - xt75-300 - color - FR - Nice - Person with hat in the water&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-07%20-%20xt75-300%20-%20color%20-%20FR%20-%20Nice%20-%20Person%20with%20hat%20in%20the%20water.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-09---xt15-45---color---FR---Nice---Building-rooftop.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-09 - xt15-45 - color - FR - Nice - Building rooftop&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-09%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Building%20rooftop.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-09---xt15-45---color---FR---Nice---Decorated-crosses-at-top-of-church.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-09 - xt15-45 - color - FR - Nice - Decorated crosses at top of church&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-09%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Decorated%20crosses%20at%20top%20of%20church.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-09---xt15-45---color---FR---Nice---Mosaic-of-ship.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-09 - xt15-45 - color - FR - Nice - Mosaic of ship&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-09%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Mosaic%20of%20ship.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-09---xt15-45---color---FR---Nice---Person-snorkeling-in-the-sea.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-09 - xt15-45 - color - FR - Nice - Person snorkeling in the sea&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-09%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Person%20snorkeling%20in%20the%20sea.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/nice/2025-09-09---xt15-45---color---FR---Nice---Waterfall.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-09 - xt15-45 - color - FR - Nice - Waterfall&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/nice/2025-09-09%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Waterfall.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;h2&gt;Menton, France&lt;/h2&gt;
&lt;p&gt;We also spent a little time exploring the region by train, my favourite stop was Menton - the entire city was pretty much just yellow and orange.
Just a short train ride from Nice - lovely beaches and a lot less busy&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Blue-window-blings-on-orange-building.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Blue window blings on orange building&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Blue%20window%20blings%20on%20orange%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Corner-of-orange-walls-along-staircase.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Corner of orange walls along staircase&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Corner%20of%20orange%20walls%20along%20staircase.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Harbor-between-two-buildings.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Harbor between two buildings&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Harbor%20between%20two%20buildings.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Many-levels-of-staricases-and-orange-walls.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Many levels of staricases and orange walls&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Many%20levels%20of%20staricases%20and%20orange%20walls.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Person-standing-amongst-small-orange-buildings.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Person standing amongst small orange buildings&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Person%20standing%20amongst%20small%20orange%20buildings.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Plants-overflowing-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Plants overflowing balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Plants%20overflowing%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Small-car-parked-on-roadside.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Small car parked on roadside&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Small%20car%20parked%20on%20roadside.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Staricases-leading-up-to-buildings-in-background.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Staricases leading up to buildings in background&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Staricases%20leading%20up%20to%20buildings%20in%20background.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Statue-with-flowers-in-the-foreground.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Statue with flowers in the foreground&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Statue%20with%20flowers%20in%20the%20foreground.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Towel-hanging-out-of-window.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Towel hanging out of window&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Towel%20hanging%20out%20of%20window.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/menton/2025-09-08---xt15-45---color---FR---Menton---Weathered-building.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - FR - Menton - Weathered building&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/menton/2025-09-08%20-%20xt15-45%20-%20color%20-%20FR%20-%20Menton%20-%20Weathered%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;h2&gt;Monte Carlo, Monaco&lt;/h2&gt;
&lt;p&gt;I wasn&amp;#39;t a huge fan of Monaco. Not very pedestrian friendly. The architecture was really interesting though, and the water was clearer than anything I&amp;#39;ve ever seen&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Blue-columns-of-balconies.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Blue columns of balconies&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Blue%20columns%20of%20balconies.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Boats-on-the-water.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Boats on the water&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Boats%20on%20the%20water.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Building-through-arch.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Building through arch&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Building%20through%20arch.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Cars-driving-up-hairpin-bend.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Cars driving up hairpin bend&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Cars%20driving%20up%20hairpin%20bend.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Construction-crane.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Construction crane&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Construction%20crane.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Flags.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Flags&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Flags.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---People-crossing-road.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - People crossing road&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20People%20crossing%20road.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---People-loking-at-huge-yacht.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - People loking at huge yacht&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20People%20loking%20at%20huge%20yacht.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---People-walking-next-to-pool.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - People walking next to pool&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20People%20walking%20next%20to%20pool.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Person-crossing-road-in-front-of-modern-building.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Person crossing road in front of modern building&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Person%20crossing%20road%20in%20front%20of%20modern%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Person-walking-in-front-of-building.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Person walking in front of building&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Person%20walking%20in%20front%20of%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Reflection-of-building-in-the-water.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Reflection of building in the water&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Reflection%20of%20building%20in%20the%20water.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/monaco/2025-09-08---xt15-45---color---MC---Monte-Carlo---Water-crashing-onto-rocks.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt15-45 - color - MC - Monte Carlo - Water crashing onto rocks&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/monaco/2025-09-08%20-%20xt15-45%20-%20color%20-%20MC%20-%20Monte%20Carlo%20-%20Water%20crashing%20onto%20rocks.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;h2&gt;Ventimiglia, Italy&lt;/h2&gt;
&lt;p&gt;Deciding to explore a bit further we took the first stop in Italy, Ventimiglia. A quiet coastal town. It&amp;#39;s weird how just crossing the border completely changes the vibe of a town&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/ventimiglia/2025-09-08---xt75-300---color---IT---Ventimiglia---Buildings-in-the-distance.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt75-300 - color - IT - Ventimiglia - Buildings in the distance&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/ventimiglia/2025-09-08%20-%20xt75-300%20-%20color%20-%20IT%20-%20Ventimiglia%20-%20Buildings%20in%20the%20distance.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/ventimiglia/2025-09-08---xt75-300---color---IT---Ventimiglia---Clothes-hanging-from-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt75-300 - color - IT - Ventimiglia - Clothes hanging from balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/ventimiglia/2025-09-08%20-%20xt75-300%20-%20color%20-%20IT%20-%20Ventimiglia%20-%20Clothes%20hanging%20from%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/ventimiglia/2025-09-08---xt75-300---color---IT---Ventimiglia---No-entry-sign-on-beach.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt75-300 - color - IT - Ventimiglia - No entry sign on beach&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/ventimiglia/2025-09-08%20-%20xt75-300%20-%20color%20-%20IT%20-%20Ventimiglia%20-%20No%20entry%20sign%20on%20beach.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/ventimiglia/2025-09-08---xt75-300---color---IT---Ventimiglia---Painted-stone-on-beach.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt75-300 - color - IT - Ventimiglia - Painted stone on beach&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/ventimiglia/2025-09-08%20-%20xt75-300%20-%20color%20-%20IT%20-%20Ventimiglia%20-%20Painted%20stone%20on%20beach.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/ventimiglia/2025-09-08---xt75-300---color---IT---Ventimiglia---Showers-on-beach-in-front-of-graffiti.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt75-300 - color - IT - Ventimiglia - Showers on beach in front of graffiti&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/ventimiglia/2025-09-08%20-%20xt75-300%20-%20color%20-%20IT%20-%20Ventimiglia%20-%20Showers%20on%20beach%20in%20front%20of%20graffiti.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;h2&gt;A side quest&lt;/h2&gt;
&lt;p&gt;I also wanted something to keep my eye on my surroundings so I could hunt for some interesting pictures,
what drew my attention was the presence of laundry hanging on windowsills or balconies pretty much everywhere in the region -
I suppose the sunny weather had something to do with that&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Bedsheets-on-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Bedsheets on balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Bedsheets%20on%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Drying-rack-on-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Drying rack on balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Drying%20rack%20on%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Laundry-and-imbrellas-on-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Laundry and imbrellas on balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Laundry%20and%20imbrellas%20on%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Launry-on-balconies-in-alley.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Launry on balconies in alley&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Launry%20on%20balconies%20in%20alley.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Many-lines-of-washing-along-building-side.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Many lines of washing along building side&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Many%20lines%20of%20washing%20along%20building%20side.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Towels-hanging-over-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Towels hanging over balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Towels%20hanging%20over%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-06---xt15-45---color---FR---Nice---Washing-hanging-on-two-buildings-facing-each-other.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-06 - xt15-45 - color - FR - Nice - Washing hanging on two buildings facing each other&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-06%20-%20xt15-45%20-%20color%20-%20FR%20-%20Nice%20-%20Washing%20hanging%20on%20two%20buildings%20facing%20each%20other.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-08---xt75-300---color---FR---Menton---Towel-hanging-outside-of-window.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2025-09-08 - xt75-300 - color - FR - Menton - Towel hanging outside of window&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-08%20-%20xt75-300%20-%20color%20-%20FR%20-%20Menton%20-%20Towel%20hanging%20outside%20of%20window.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/places/2025-09-cote-d-azure/laundry/2025-09-08---xt75-300---color---IT---Ventimiglia---Washing-hanging-outside-of-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2025-09-08 - xt75-300 - color - IT - Ventimiglia - Washing hanging outside of balcony&quot; src=&quot;/optimized-images/content/photography/places/2025-09-cote-d-azure/laundry/2025-09-08%20-%20xt75-300%20-%20color%20-%20IT%20-%20Ventimiglia%20-%20Washing%20hanging%20outside%20of%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;p&gt;I also just want to say - damn, Fuji colours, amiright? -
that&amp;#39;s about it, thanks for reading!&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Typescript Workers in NodeJS</title><link>https://nabeelvalley.co.za/blog/2025/12-02/nodejs-worker-threads.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/12-02/nodejs-worker-threads.html</guid><description>Basic Setup for using workers in NodeJS with Typescript</description><pubDate>Wed, 12 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Typescript Workers in NodeJS&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Using worker threads with Typescript is pretty straightforward, this probably depends a bit on your setup but the below idea seems to work for me&lt;/p&gt;
&lt;h2&gt;Single File Worker&lt;/h2&gt;
&lt;p&gt;In NodeJS we can use a sort of self-referrential worker such that depending on the context in which the file is loaded the behavior will differ, for example:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Worker, isMainThread, parentPort, workerData } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;node:worker_threads&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// the worker is the current file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; workerFileName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; __filename&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// define a type for the data we want to share&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WorkerData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// check if we&amp;#39;re on the main or worker thread&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (isMainThread) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // launch a worker thread&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;reject&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Worker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(workerFileName, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // pass data to the worker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      workerData: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        id: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;my-worker&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Bob&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;result&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, reject)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;then&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(console.log)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;} &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;else&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do stuff for the worker thread&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Running in worker&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, workerData &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;as&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WorkerData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; message&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `Hello ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;workerData&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} from worker`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // return back to the parent thread&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  parentPort?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ message })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above file we can see a few things that are important to using workers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A check is done using &lt;code&gt;isMainThread&lt;/code&gt; to determine if the file is being executed as a worker. the handling for the worker is based on this&lt;/li&gt;
&lt;li&gt;A reference to the file which should be run in the worker thread, the &lt;code&gt;__filename&lt;/code&gt; variable is defined by NodeJS and holds the name of the curent file - this will be the compiled file name so we don&amp;#39;t need to figure that out on our own &lt;/li&gt;
&lt;li&gt;A worker is created using &lt;code&gt;new Worker&lt;/code&gt;, since the worker is an event based API in the above example it&amp;#39;s being wrapped in a &lt;code&gt;Promise&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Data can be passed to the worker via the &lt;code&gt;workerData&lt;/code&gt; property, this will then be put into the &lt;code&gt;workerData&lt;/code&gt; variable from &lt;code&gt;node:worker_threads&lt;/code&gt; in the worker thread&lt;/li&gt;
&lt;li&gt;Data is sent back to the worker using &lt;code&gt;parentPort.postMessage&lt;/code&gt;. This is the same even that&amp;#39;s being listened for the &lt;code&gt;Promise&lt;/code&gt; to resolve in &lt;code&gt;worker.addListener(&amp;quot;message&amp;quot;, resolve)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Multi File Worker&lt;/h2&gt;
&lt;p&gt;Extending the above to work with multiple files is pretty simple, the only additional trick we need is to export the &lt;code&gt;__filename&lt;/code&gt; from our worker file to the place where we want to construct the worker&lt;/p&gt;
&lt;p&gt;So, the updated code can then be broken into two files as follows:&lt;/p&gt;
&lt;p&gt;First, the worker is pretty similar to the one above, except now we export the &lt;code&gt;__filename&lt;/code&gt; as &lt;code&gt;workerFileName&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { isMainThread, parentPort, workerData } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;node:worker_threads&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; workerFileName&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; __filename&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;export&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; WorkerData&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  name&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;isMainThread) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Running in worker&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, workerData)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; message&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `Hello ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;workerData&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;} from worker`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  parentPort?.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;postMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ message })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;} &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;else&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Worker was run in the main thread&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;main.ts&lt;/code&gt; file then makes use of this exported file name to invoke the worker. Note that this is now just a normal script and will be executed in the main thread as normal&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { Worker } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;node:worker_threads&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// import the worker file name from where we defined the worker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { workerFileName } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;./worker&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; workers&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;4&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;].&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;reject&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Worker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(workerFileName, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    workerData: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      id,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`Bob ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;id&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;result&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({ id, result }))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  worker.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;addListener&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, reject)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;async&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; results&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;all&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(workers)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(results)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Uncompiled Worker Using &lt;code&gt;ts-node&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;When executing workers it&amp;#39;s also possible to execute the Typescript file directly instead of relying on the compilation. This can be useful for cases where the Javascript code is compiled to a single file or in situations where you don&amp;#39;t have control over the execution environment&lt;/p&gt;
&lt;p&gt;Executing a Typescript worker can be done by using &lt;code&gt;ts-node&lt;/code&gt; when running the worker, an example of this is:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; worker&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Worker&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;my-worker.ts&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    execArgv: [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;-r&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;ts-node/register&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--no-warnings&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    workerData: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// do stuff with the worker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nodejs.org/api/worker_threads.html&quot; &gt;NodeJS Worker Threads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Week 37, Server Management</title><link>https://nabeelvalley.co.za/blog/2025/14-09/week-37-server-management.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/14-09/week-37-server-management.html</guid><description>Some utilities that simplify self hosting</description><pubDate>Sun, 14 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Week 37, Server Management&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Off topic&lt;/h2&gt;
&lt;p&gt;Something off-topic but I just came across &lt;a href=&quot;https://biomousavi.com/difference-between-process-nexttick-setimmediate-and-settimeout-in-node-js&quot; &gt;this explainer&lt;/a&gt; on the different task queues and related methods in Node.js that I thought would be a nice share&lt;/p&gt;
&lt;h2&gt;What I Found&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve been looking into/exploring some solutions for self hosting and had a little exploration/review of some tools with &lt;a href=&quot;https://kurtlourens.com/&quot; &gt;Kurt Lourens&lt;/a&gt; on some of the tech that&amp;#39;s available&lt;/p&gt;
&lt;h3&gt;Proxies&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/traefik/traefik&quot; &gt;Traefik&lt;/a&gt; is a reverse proxy that integrates really nicely with Docker by letting you configure endpoints via the container configuration in your environment&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/caddyserver/caddy&quot; &gt;Caddy&lt;/a&gt; is a web server and reverse proxy that supports TLS out of the box and is really nice to configure&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Application Management&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/portainer/portainer&quot; &gt;Portainer&lt;/a&gt; is a management layer and UI for Docker and Kubernetes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ofkm/arcane&quot; &gt;Arcane&lt;/a&gt; is another UI for managing Docker containers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/moghtech/komodo&quot; &gt;Komodo&lt;/a&gt; is a tool that simplifies the building and deployment of software across many servers&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Parsing Helix logs in Nushell</title><link>https://nabeelvalley.co.za/blog/2025/16-12/helix-log-parsing.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/16-12/helix-log-parsing.html</guid><pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Parsing Helix logs in Nushell&lt;/h1&gt;&lt;site-markdown&gt;&lt;h2&gt;Getting Helix Logs&lt;/h2&gt;
&lt;p&gt;Viewing helix logs can be done by reading &lt;code&gt;~/.cache/helix/helix.log&lt;/code&gt;. To increase logging verbosity, you should also start helix with &lt;code&gt;hx -v&lt;/code&gt; which will provide more detailed logs which can be handy for debugging language servers&lt;/p&gt;
&lt;h2&gt;Parsing a Log&lt;/h2&gt;
&lt;p&gt;A super quick one today - I was doing some debugging on a &lt;a href=&quot;/blog/2025/26-03/the-language-server-protocol&quot; &gt;Language Server&lt;/a&gt; for &lt;a href=&quot;https://helix-editor.com/&quot; &gt;Helix&lt;/a&gt; and it was getting really annoying trying to find the data I was looking for so I wrote this quick &lt;a href=&quot;https://www.nushell.sh/&quot; &gt;Nushell&lt;/a&gt; command:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;cat&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ~/.cache/helix/helix.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parse&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;{date} helix_lsp::transport [{type}] {source} &amp;lt;- {data}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will parse the Helix logs using the given format.&lt;/p&gt;
&lt;h2&gt;Parsing inner JSON&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;data&lt;/code&gt; portion is also JSON, so adding the JSON parsing can be done with:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;cat&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ~/.cache/helix/helix.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parse&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;{date} helix_lsp::transport [{type}] {source} &amp;lt;- {data}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; update&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; {&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $e&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Rendering with &lt;code&gt;jq&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I also prefer normal JSON to the helix data view for this kind of data, so you can tac on &lt;code&gt;| to json | jq&lt;/code&gt; to pipe it to &lt;a href=&quot;https://jqlang.org/&quot; &gt;jq&lt;/a&gt; for some nice JSON rendering and querying:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;cat&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ~/.cache/helix/helix.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parse&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;{date} helix_lsp::transport [{type}] {source} &amp;lt;- {data}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; update&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; {&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $e&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; jq&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Real-time log rendering&lt;/h2&gt;
&lt;p&gt;And for real-time rendering/printing, you can use &lt;code&gt;tail&lt;/code&gt; + &lt;code&gt;each { print }&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tail&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -f&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ~/.cache/helix/helix.log&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; parse&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;{date} {section} [{type}] {source} &amp;lt;- {data}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; update&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; data&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; {&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; from&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; each&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; {&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; to&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; jq&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -C&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; print&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Generator Generation</title><link>https://nabeelvalley.co.za/blog/2025/17-12/generator-generation.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/17-12/generator-generation.html</guid><description>Converting callback based APIs into Async Generators in JavaScript/Typescript</description><pubDate>Wed, 17 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Generator Generation&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;So I was just going to write a short post about this handy function I made, but I thought it would be a nice opportunity to build a little bit more of an understanding around the topic of generators more broadly&lt;/p&gt;
&lt;p&gt;Our end goal is going to be to define an abstraction that will allow us to convert any Callback-Based API into an Async Generator. Now, if those words don’t mean much to you, then welcome to the other side of JavaScript. If you’re just here for the magic function, however, feel free to skip to the end&lt;/p&gt;
&lt;h2&gt;Promises&lt;/h2&gt;
&lt;p&gt;Before diving into the complexity of generators, we&amp;#39;re going to quickly kick off with a little introduction to &lt;code&gt;Promises&lt;/code&gt; and how they relate to &lt;code&gt;async/await&lt;/code&gt; and callback-based code&lt;/p&gt;
&lt;p&gt;Promises are used to make async code easier to work with and JavaScript has some nice syntax - like &lt;code&gt;async/await&lt;/code&gt; that makes code using promises easier follow and understand. They&amp;#39;re also the common way to represent async operations which is exactly what we&amp;#39;re going to use them for&lt;/p&gt;
&lt;p&gt;Before we can dive right into implementing our function for creating an &lt;code&gt;AsyncGenerator&lt;/code&gt; from a callback based API, it&amp;#39;s important to understand how we might go about wrapping a callback based API into a &lt;code&gt;Promise&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Creating Promises from Callbacks&lt;/h3&gt;
&lt;p&gt;Often we end up in cases where we&amp;#39;ve got some code that is callback based - this is a function, for example &lt;code&gt;setTimeout&lt;/code&gt;, that will invoke the rest of our code asynchronously when some task is done or event is received&lt;/p&gt;
&lt;p&gt;A simple example of a callback based function is &lt;code&gt;setTimeout&lt;/code&gt; which will resume the execution of our code after some specified amount of time:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setTimeout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;this runs after 1000ms&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;A common usecase is to convert this to a &lt;code&gt;Promise&lt;/code&gt; so that consumers can work with this using &lt;code&gt;async&lt;/code&gt; functions and &lt;code&gt;await&lt;/code&gt;ing the relevant function call&lt;/p&gt;
&lt;p&gt;The basic method for doing this consists of returning a &lt;code&gt;Promise&lt;/code&gt; and handling the rejection or resolution within the callback. For example, we can create a promise-based version of &lt;code&gt;setTimeout&lt;/code&gt; using this approach:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;timeout&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;_reject&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    setTimeout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(resolve, timeout)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This promise will now resolve when &lt;code&gt;setTimeout&lt;/code&gt; calls the &lt;code&gt;resolve&lt;/code&gt; method that&amp;#39;s been passed to it. This allows us to turn some callback based code like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;setTimeout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;done&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Into this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;done&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Granted, this isn&amp;#39;t a huge difference - the value of this comes from when we have multiple of these kinds of calls nested within each other. Callback code is notorious for its tendency towards chaos. My rule of thumb on this is basically &amp;quot;less indentation is easier to understand&amp;quot;. And if we can avoid indentation and keep our code flat we can focus on the essential complexity of our application and not the cognitive load that comes with confusing scope, syntax, and callbacks&lt;/p&gt;
&lt;p&gt;This is such a common problem in the JavaScript world, that Node.js even has a builtin function &lt;code&gt;node:util&lt;/code&gt; called &lt;code&gt;promisify&lt;/code&gt; that converts Node.js style callback functions into promise-based ones&lt;/p&gt;
&lt;h3&gt;Async/Await&lt;/h3&gt;
&lt;p&gt;When working with promises, it&amp;#39;s useful to define our methods using the &lt;code&gt;async&lt;/code&gt; keyword, this allows us to work with a &lt;code&gt;Promise&lt;/code&gt; using &lt;code&gt;await&lt;/code&gt; and not have any callbacks&lt;/p&gt;
&lt;p&gt;So we can have our function below, which can &lt;code&gt;await&lt;/code&gt; the &lt;code&gt;sleep&lt;/code&gt; function and it would be defined like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;async&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;fine, time to work now&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;doWork&lt;/code&gt; function returns &lt;code&gt;Promise&lt;/code&gt;, this is because the &lt;code&gt;async&lt;/code&gt; keyword is some syntax sugar for creating a &lt;code&gt;Promise&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Promises Vs Async&lt;/h3&gt;
&lt;p&gt;For the sake of understanding, all that the &lt;code&gt;async&lt;/code&gt; keyword does allow us to remove the &lt;code&gt;Promise&lt;/code&gt; construction from our function - &lt;code&gt;async&lt;/code&gt; functions are simply functions that return a &lt;code&gt;Promise&lt;/code&gt; - these are alternative syntax for the same thing - so, the following two functions are the same:&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;async&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;async&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getNumber&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using an explicit &lt;code&gt;Promise&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getNumber&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Promise.withResolvers&lt;/h3&gt;
&lt;p&gt;Another pattern that often comes us is the need to reach into the &lt;code&gt;Promise&lt;/code&gt; constructor and grab onto its &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; methods and pass them around so that we can &amp;quot;remotely&amp;quot; compelete a &lt;code&gt;Promise&lt;/code&gt;, as per MDN, the common pattern for doing this looks something like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; withResolvers&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; resolve&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;v&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; reject&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; unknown&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  new&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;rej&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    resolve &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; res&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    reject &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; rej&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    resolve,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    reject,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This method is also a recent addition to the &lt;code&gt;Promise&lt;/code&gt; class via &lt;code&gt;Promise.withResolvers&lt;/code&gt;, but for cases where it&amp;#39;s not - the above should serve the equivalent purpose&lt;/p&gt;
&lt;p&gt;Now that we&amp;#39;ve got an understanding of Promises, it&amp;#39;s time to talk about Iterators and Generators&lt;/p&gt;
&lt;h2&gt;Iterators and Generators&lt;/h2&gt;
&lt;p&gt;Iterators and generators enable iteration to work in JavaScript and are what lies behind objects that are iterable by way of a &lt;code&gt;for ... of&lt;/code&gt; loop&lt;/p&gt;
&lt;h3&gt;Iterator&lt;/h3&gt;
&lt;p&gt;An iterator is basically an object that will return a new value whenever its &lt;code&gt;next&lt;/code&gt; method is called&lt;/p&gt;
&lt;p&gt;A simple iterator can be defined as an object that has a &lt;code&gt;next&lt;/code&gt; method that returns whether it&amp;#39;s &lt;code&gt;done&lt;/code&gt; or not.&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countToIterator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Iterator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; iterator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Iterator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        done: value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; max,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; iterator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;JavaScript uses the &lt;code&gt;Symbol.iterator&lt;/code&gt; property to reference this object and therefore makes it possible for the language &lt;code&gt;for ... of&lt;/code&gt; loop to iterate through this object. We can use the &lt;code&gt;countToIterator&lt;/code&gt;&amp;#39;s returned &lt;code&gt;iterator&lt;/code&gt; to define an &lt;code&gt;Iterable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;What a mouthful right?? - But the implementation is actually easier than the description:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countTo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Iterable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; iterator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countToIterator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(max)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [Symbol.iterator]() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; iterator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Once we&amp;#39;ve got this, we can use the &lt;code&gt;countTo&lt;/code&gt; in a loop:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// counts from 1 to 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; v&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countTo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Could this be an array? Maybe. Arrays are really just a special case of an iterator. More generally, iterators are cool because they don&amp;#39;t have to have a fixed endpoint, or even a fixed list of values. For example, we can create a different iterator that counts until a random point by modifying how the &lt;code&gt;next&lt;/code&gt; function works:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; randomlyStopCounting&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Iterable&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; iterator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Iterator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        done: Math.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;random&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0.8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [Symbol.iterator]() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; iterator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; v&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; randomlyStopCounting&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This is used the same as above, but the point at which this will return isn&amp;#39;t really known beforehand. This dynamic behavior can come from lots of different places and not just from &lt;code&gt;Math.random&lt;/code&gt; and it can allow some really interesting behaviors&lt;/p&gt;
&lt;h3&gt;Generators&lt;/h3&gt;
&lt;p&gt;Defining the above iterators is fun and all, but it&amp;#39;s quite messy. The higher-order syntax for defining these kinds of iterators is using &lt;code&gt;Generators&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(I know, what&amp;#39;s with all these words right??)&lt;/p&gt;
&lt;p&gt;Okay, so generator functions are functions that return a special iterator called a &lt;code&gt;Generator&lt;/code&gt;. If we weren&amp;#39;t into the territory of weird syntax already - generators are defined using the &lt;code&gt;function*&lt;/code&gt; keyword, and use the &lt;code&gt;yield&lt;/code&gt; keyword to provide the next value. So we can rewrite our &lt;code&gt;countTo&lt;/code&gt; function using a generator function and it would look like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function*&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countTo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Generator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  while&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; max) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    yield&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;That&amp;#39;s actually way nicer to read right? When we &lt;code&gt;yield&lt;/code&gt; a value the flow is delegated to the loop body, just like in the case of a normal iterator, which means the consumer can actually end the iteration early, like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; v&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countTo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (v &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    break&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This also applies for the iterators above, I just find it so much more interesting in this case because there&amp;#39;s no concept that someone is going to &amp;quot;call the &lt;code&gt;next&lt;/code&gt; method again&amp;quot; which is so transparent in the iterator example above&lt;/p&gt;
&lt;h3&gt;Async Generators&lt;/h3&gt;
&lt;p&gt;Now, we&amp;#39;re taking one more step - what if I wanted to do some long running task between each &lt;code&gt;yield&lt;/code&gt;? This could be anything from waiting for a &lt;code&gt;Promise&lt;/code&gt; to resolve, or a network request, or some user event (oh wow - there&amp;#39;s an idea for multistep forms!)&lt;/p&gt;
&lt;p&gt;Async Generators enable us to use promises in our iterators. Let&amp;#39;s take a look at how we might define an async version of our &lt;code&gt;countTo&lt;/code&gt; generator above:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;async&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; function*&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countToAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  while&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; max) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    yield&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Almost exactly the same right? Aside from the sneaky &lt;code&gt;async&lt;/code&gt; keyword and the &lt;code&gt;await&lt;/code&gt; in the loop, this is pretty similar to the sync version above. Using this also has a new little twist, can you spot it?:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; v&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countToAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;async count&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Interesting right? We&amp;#39;re now using a &lt;code&gt;for await ... of&lt;/code&gt; loop. If you were to run this, you&amp;#39;d also notice that there&amp;#39;s a little pause between each value being logged&lt;/p&gt;
&lt;h2&gt;Unwrapping the Generator&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve seen what the inside of an iterator looks like - it&amp;#39;s time to open the box and see what generators have inside&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s start with the sync version&lt;/p&gt;
&lt;h3&gt;Inside a Sync Generator&lt;/h3&gt;
&lt;p&gt;So if we redefine our &lt;code&gt;countTo&lt;/code&gt; generator without using the &lt;code&gt;function*&lt;/code&gt; and &lt;code&gt;yield&lt;/code&gt; syntax sugar, we&amp;#39;ll see something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countTo&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Generator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; generator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Generator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [Symbol.iterator]() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; generator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        done: value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; max,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      throw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; generator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This looks &lt;strong&gt;very&lt;/strong&gt; similar to an iterator - and that&amp;#39;s because it is!&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Generator&lt;/code&gt; type inherits from the &lt;code&gt;Iterator&lt;/code&gt; and needs an additional &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;throw&lt;/code&gt; methods. The &lt;code&gt;return&lt;/code&gt; method allows the generator to handle any cleanup once the consumer is done iterating. The &lt;code&gt;throw&lt;/code&gt; allows any handling of errors and any other cleanup tasks&lt;/p&gt;
&lt;h3&gt;Inside an Async Generator&lt;/h3&gt;
&lt;p&gt;The async version of the above is almost identical - but we just sprinkle the &lt;code&gt;async&lt;/code&gt; keyword around to make the respective methods all return a &lt;code&gt;Promise&lt;/code&gt; as this is what the &lt;code&gt;AsyncGenerator&lt;/code&gt; requires:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countToAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; generator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [Symbol.asyncIterator]() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; generator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        done: value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; max,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; throw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      throw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; generator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; v&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countToAsync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;async count&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, v)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Just like when defining the Async Generator before, we&amp;#39;re just calling &lt;code&gt;sleep&lt;/code&gt; between each return value. We&amp;#39;ve also made the &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;throw&lt;/code&gt; methods &lt;code&gt;async&lt;/code&gt; as well&lt;/p&gt;
&lt;h2&gt;Creating Generators from Callback Functions&lt;/h2&gt;
&lt;p&gt;Well, it&amp;#39;s been a long way, but we finally have all the tools we need to turn a callback based method into an iterator. So far, we&amp;#39;ve been using &lt;code&gt;setTimeout&lt;/code&gt; for our callbacks, but generators return multiple values. We&amp;#39;re going to create a little modified version of &lt;code&gt;setInterval&lt;/code&gt; for this so that we can play around&lt;/p&gt;
&lt;p&gt;The version we&amp;#39;ll define is called &lt;code&gt;countInterval&lt;/code&gt; and will emit a new number until the given value and then stop, this looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  onValue&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;num&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  onDone&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; interval&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (value &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; max) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      clearInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(interval)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;      onDone&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    onValue&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the usage looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;countInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;v&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;count interval&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, v),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;count interval done&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Assume for whatever reason that we want to be able to take functions like this and turn them into generators. In general, we can go about the process of manually defining a generator, but that&amp;#39;s a little tedious and requires managing a lot of internal state. It would be nice if we could do this without having to manage the intricate details of a custom generator. We basically want to define &lt;code&gt;countInterval&lt;/code&gt; such that it looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countIntervalGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;For now, let&amp;#39;s assume we&amp;#39;ve got a method called &lt;code&gt;createGenerator&lt;/code&gt; that returns everything we need in order to hook up a generator and return it, this looks something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countIntervalGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;max&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;generator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;done&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;number&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  countInterval&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(max, next, done)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; generator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And our new generator can be used just as usual:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;for&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; of&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; countIntervalGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;count interval generator&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Defining this wonderful &lt;code&gt;createGenerator&lt;/code&gt; function combines what we&amp;#39;ve learnt about promises and generators to get this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; current &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;withResolvers&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; final &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;withResolvers&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; generator&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; AsyncGenerator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    [Symbol.asyncIterator]() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; generator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; final.promise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        done: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; next&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; current.promise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        done: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        value,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    async&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; throw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;e&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      throw&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; next&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;value&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; T&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    current.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(value)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    current &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;withResolvers&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; done&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    final.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    next,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    done,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    generator,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This isn&amp;#39;t doing anything that we haven&amp;#39;t covered before. The only interesting bit (in my opinion) is how the &lt;code&gt;next&lt;/code&gt; handler creates a new promise on each iteration - this implementation probably has some weirdness due to that so in practice you probably want to handle that edge case somewhat. This could maybe be done by updating the &lt;code&gt;next&lt;/code&gt; function to take a parameter to indicate if it will emit a new value or not but in practice it&amp;#39;s not always easy to figure that out - and in many cases you just don&amp;#39;t know&lt;/p&gt;
&lt;p&gt;That all being said, I think this implementation should make it clear how these pieces all fit together - there&amp;#39;s a lot more detail that can be had in this discussion since each of these topics are fairly deep - but I hope this post was - if not useful - then at least interesting&lt;/p&gt;
&lt;h2&gt;References and Further Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot; &gt;MDN: Promise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers&quot; &gt;MDN: Promise.withResolvers()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators&quot; &gt;MDN: Iterators and generators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols&quot; &gt;MDN: Iterator protocols&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield*&quot; &gt;MDN: yield*&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nodejs.org/api/util.html#utilpromisifyoriginal&quot; &gt;Node.js: util.promisify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Typescript debugging without an IDE</title><link>https://nabeelvalley.co.za/blog/2025/18-06/typescript-debugging-without-an-ide.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/18-06/typescript-debugging-without-an-ide.html</guid><description>Debug Node.js code using your browser&#39;s dev tools</description><pubDate>Wed, 18 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Typescript debugging without an IDE&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I generally steer clear of IDEs. Their overall slowness and clunkyness makes using them a hassle. There is however one place they execel - debugging. &lt;/p&gt;
&lt;p&gt;Recently I&amp;#39;ve been looking into how to get Node.js to debug some JS and TS code and this proved to be relatively simple&lt;/p&gt;
&lt;h2&gt;A JS file&lt;/h2&gt;
&lt;p&gt;Debugging a Javascript app is actually pretty straightforward, you can use &lt;code&gt;node inspect&lt;/code&gt; followed by the file to debug. So this just looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; inspect&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-file.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Runnning the above with a &lt;code&gt;debugger;&lt;/code&gt; statement in your code will stop at the breakpoint and you can debug from there&lt;/p&gt;
&lt;p&gt;You can then open your browser at &lt;code&gt;chrome://inspect&lt;/code&gt; and select &lt;code&gt;inspect&lt;/code&gt; on the process you&amp;#39;d like to debug&lt;/p&gt;
&lt;h2&gt;A TS File&lt;/h2&gt;
&lt;p&gt;Typescript requires you to have a few things installed. I&amp;#39;m going to assume that TypeScript is already installed in the project you&amp;#39;re working in. Additionally, you need to install &lt;code&gt;ts-node&lt;/code&gt; into your project - this can be done using whatever package manager you&amp;#39;re currently using&lt;/p&gt;
&lt;p&gt;You will also need to ensure that you have &lt;code&gt;sourceMap&lt;/code&gt; enabled in your &lt;code&gt;tsconfig.json&lt;/code&gt; file in order to have a bit of a decent debugging experience:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;compilerOptions&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;	// ... other stuff&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;sourceMap&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, you can use &lt;code&gt;node inspect&lt;/code&gt; with the &lt;code&gt;ts-loader&lt;/code&gt; like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;node&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; inspect&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -r&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ts-node/register&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; my-file.ts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The process then is pretty much the same as for the Javascript file debugging above. You can use &lt;code&gt;debugger;&lt;/code&gt; statements to add breakpoints, and you can open the debugger at &lt;code&gt;chrome://inspect&lt;/code&gt;&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Getting Started with the Language Server Protocol</title><link>https://nabeelvalley.co.za/blog/2025/26-03/the-language-server-protocol.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/26-03/the-language-server-protocol.html</guid><description>Building a Basic Language Server with JavaScript</description><pubDate>Wed, 26 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Getting Started with the Language Server Protocol&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Note that the code here serves as a high level example for the development of a language server and is in no means intended to be a production-ready implementation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;The Language Server Protocol&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot; &gt;Language Server Protocol Specification&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Language Server Protocol (LSP) is a specification for communication between code editing applications and language servers that provide information about the programming language being worked with&lt;/p&gt;
&lt;p&gt;The protocol enables language related functionality such as diagnostics or documentation to be implemented once and reused in all editors that support LSP&lt;/p&gt;
&lt;p&gt;The specification uses &lt;a href=&quot;https://www.jsonrpc.org/specification&quot; &gt;JSON RPC 2.0&lt;/a&gt; for communicating between the editor and language server&lt;/p&gt;
&lt;h2&gt;Creating a Basic Language Server&lt;/h2&gt;
&lt;h3&gt;Input and Output&lt;/h3&gt;
&lt;p&gt;A basic language server can be created using standard in and out as the communication mechanism for the server. This is quite easy to get access to using Node.js as we can get it from &lt;code&gt;process&lt;/code&gt; like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;stdout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;stdin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;process&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stdin&lt;/code&gt; are streams, we can read from the &lt;code&gt;stdin&lt;/code&gt; stream using the &lt;code&gt;data&lt;/code&gt; event, and we can write to &lt;code&gt;stdout&lt;/code&gt; directly&lt;/p&gt;
&lt;p&gt;The code editor that&amp;#39;s managing the language server will pass data to it using &lt;code&gt;stdin&lt;/code&gt;, responses need to be sent using &lt;code&gt;stdout&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Each message that&amp;#39;s sent/received consists of two parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A headers section containing a &lt;code&gt;Content-Length&lt;/code&gt; header structured like &lt;code&gt;Content-Length: 123&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A content section&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The header and content sections are separated by &lt;code&gt;\r\n\r\n&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The overall structure looks like this (&lt;code&gt;\r\n&lt;/code&gt; shown as well since they are a strictly considered in the message)&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;txt&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Content-Length: 123\r\n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;\r\n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;id&amp;quot;: 1,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;method&amp;quot;: &amp;quot;example/method&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;params&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;There are two types of messages, namely &lt;code&gt;Request&lt;/code&gt;s and &lt;code&gt;Notification&lt;/code&gt;s. &lt;code&gt;Request&lt;/code&gt; messages require a response. The &lt;code&gt;id&lt;/code&gt; of the message is relevant and is sent back with a response, a &lt;code&gt;Response&lt;/code&gt; looks a bit like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;txt&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Content-Length: 123\r\n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;\r\n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;id&amp;quot;: 1,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;result&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The other type of message is a &lt;code&gt;Notification&lt;/code&gt;. &lt;code&gt;Notification&lt;/code&gt; messages don&amp;#39;t require a &lt;code&gt;Response&lt;/code&gt;. Additionally, they will not have an &lt;code&gt;id&lt;/code&gt; and will look something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;txt&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Content-Length: 123\r\n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;\r\n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;quot;params&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3&gt;Initializing the Project&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;#39;m assuming you&amp;#39;ve got some basic idea of how Node.js works and that you&amp;#39;re familiar with the overall idea of creating a CLI tool with Node.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since the language server needs a command, we need to do a little thing with &lt;code&gt;npm&lt;/code&gt; to register the server as a command. This can be done by first defining our language server as a &lt;code&gt;bin&lt;/code&gt;. To do this we need a JS file with the language server&lt;/p&gt;
&lt;p&gt;In this example, I&amp;#39;m creating a folder with the following two files:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;cli.js&lt;/code&gt; - the language server&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the &lt;code&gt;cli.js&lt;/code&gt; you can simply add something like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;#!/usr/bin/env node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;console.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Hello from Language Server&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Next, you&amp;#39;ll need to add the following to a &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example-lsp&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;version&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;1.0.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;license&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;MIT&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;bin&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./cli.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;bin&lt;/code&gt; fields are needed so that &lt;code&gt;npm&lt;/code&gt; knows how to call your command after installing it.&lt;/p&gt;
&lt;p&gt;Once the above two files are in place, you can install/register your command using:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;npm i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will make the &lt;code&gt;example-lsp&lt;/code&gt; command available and it will automatically run the &lt;code&gt;cli.js&lt;/code&gt; file&lt;/p&gt;
&lt;h3&gt;Linking to an Editor&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The example below is for Helix, on other editors this process is different and is not the focus of this post&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Language servers are started by or connected to from the code editing application. I&amp;#39;m using &lt;a href=&quot;https://helix-editor.com/&quot; &gt;Helix&lt;/a&gt; which uses a config file that specifies the available language servers. We can reference the server we&amp;#39;ve created in Helix&amp;#39;s &lt;code&gt;languages.toml&lt;/code&gt; file like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;toml&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## define the language server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;language-server&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;example&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;command = &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example-lsp&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;## associate a language with the language server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[[&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;language&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;name = &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;scope = &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;source.example&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;file-types = [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;language-servers = [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Seeing your editor&amp;#39;s logs may vary so I&amp;#39;m not going to get too into that, but if you&amp;#39;re trying to debug issues with a language server that&amp;#39;s probably a good place to start&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Handling Messages&lt;/h3&gt;
&lt;p&gt;Once we&amp;#39;ve got our editor setup, we should be able to open a file with a &lt;code&gt;.example&lt;/code&gt; extension which will trigger our LSP&lt;/p&gt;
&lt;p&gt;When the language server is started it will receive an &lt;code&gt;initialize&lt;/code&gt; event which will look something like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;txt&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Content-Length: 2011&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;,&amp;quot;method&amp;quot;:&amp;quot;initialize&amp;quot;,&amp;quot;params&amp;quot;:{&amp;quot;capabilities&amp;quot;:{&amp;quot;general&amp;quot;:{&amp;quot;positionEncodings&amp;quot;:[&amp;quot;utf-8&amp;quot;,&amp;quot;utf-32&amp;quot;,&amp;quot;utf-16&amp;quot;]},&amp;quot;textDocument&amp;quot;:{&amp;quot;codeAction&amp;quot;:{&amp;quot;codeActionLiteralSupport&amp;quot;:{&amp;quot;codeActionKind&amp;quot;:{&amp;quot;valueSet&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;quickfix&amp;quot;,&amp;quot;refactor&amp;quot;,&amp;quot;refactor.extract&amp;quot;,&amp;quot;refactor.inline&amp;quot;,&amp;quot;refactor.rewrite&amp;quot;,&amp;quot;source&amp;quot;,&amp;quot;source.organizeImports&amp;quot;]}},&amp;quot;dataSupport&amp;quot;:true,&amp;quot;disabledSupport&amp;quot;:true,&amp;quot;isPreferredSupport&amp;quot;:true,&amp;quot;resolveSupport&amp;quot;:{&amp;quot;properties&amp;quot;:[&amp;quot;edit&amp;quot;,&amp;quot;command&amp;quot;]}},&amp;quot;completion&amp;quot;:{&amp;quot;completionItem&amp;quot;:{&amp;quot;deprecatedSupport&amp;quot;:true,&amp;quot;insertReplaceSupport&amp;quot;:true,&amp;quot;resolveSupport&amp;quot;:{&amp;quot;properties&amp;quot;:[&amp;quot;documentation&amp;quot;,&amp;quot;detail&amp;quot;,&amp;quot;additionalTextEdits&amp;quot;]},&amp;quot;snippetSupport&amp;quot;:true,&amp;quot;tagSupport&amp;quot;:{&amp;quot;valueSet&amp;quot;:[1]}},&amp;quot;completionItemKind&amp;quot;:{}},&amp;quot;formatting&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:false},&amp;quot;hover&amp;quot;:{&amp;quot;contentFormat&amp;quot;:[&amp;quot;markdown&amp;quot;]},&amp;quot;inlayHint&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:false},&amp;quot;publishDiagnostics&amp;quot;:{&amp;quot;tagSupport&amp;quot;:{&amp;quot;valueSet&amp;quot;:[1,2]},&amp;quot;versionSupport&amp;quot;:true},&amp;quot;rename&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:false,&amp;quot;honorsChangeAnnotations&amp;quot;:false,&amp;quot;prepareSupport&amp;quot;:true},&amp;quot;signatureHelp&amp;quot;:{&amp;quot;signatureInformation&amp;quot;:{&amp;quot;activeParameterSupport&amp;quot;:true,&amp;quot;documentationFormat&amp;quot;:[&amp;quot;markdown&amp;quot;],&amp;quot;parameterInformation&amp;quot;:{&amp;quot;labelOffsetSupport&amp;quot;:true}}}},&amp;quot;window&amp;quot;:{&amp;quot;workDoneProgress&amp;quot;:true},&amp;quot;workspace&amp;quot;:{&amp;quot;applyEdit&amp;quot;:true,&amp;quot;configuration&amp;quot;:true,&amp;quot;didChangeConfiguration&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:false},&amp;quot;didChangeWatchedFiles&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:true,&amp;quot;relativePatternSupport&amp;quot;:false},&amp;quot;executeCommand&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:false},&amp;quot;fileOperations&amp;quot;:{&amp;quot;didRename&amp;quot;:true,&amp;quot;willRename&amp;quot;:true},&amp;quot;inlayHint&amp;quot;:{&amp;quot;refreshSupport&amp;quot;:false},&amp;quot;symbol&amp;quot;:{&amp;quot;dynamicRegistration&amp;quot;:false},&amp;quot;workspaceEdit&amp;quot;:{&amp;quot;documentChanges&amp;quot;:true,&amp;quot;failureHandling&amp;quot;:&amp;quot;abort&amp;quot;,&amp;quot;normalizesLineEndings&amp;quot;:false,&amp;quot;resourceOperations&amp;quot;:[&amp;quot;create&amp;quot;,&amp;quot;rename&amp;quot;,&amp;quot;delete&amp;quot;]},&amp;quot;workspaceFolders&amp;quot;:true}},&amp;quot;clientInfo&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;helix&amp;quot;,&amp;quot;version&amp;quot;:&amp;quot;25.01.1 (e7ac2fcd)&amp;quot;},&amp;quot;processId&amp;quot;:34756,&amp;quot;rootPath&amp;quot;:&amp;quot;/example-lsp&amp;quot;,&amp;quot;rootUri&amp;quot;:&amp;quot;file:///example-lsp&amp;quot;,&amp;quot;workspaceFolders&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;example-lsp&amp;quot;,&amp;quot;uri&amp;quot;:&amp;quot;file:///example-lsp&amp;quot;}]},&amp;quot;id&amp;quot;:0}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We want to try to view and process this message on the language server.The first thing we&amp;#39;re going to run into when trying do this is that we can&amp;#39;t log things anymore since the &lt;code&gt;stdout&lt;/code&gt; is used as a way to send messages to the code editor - so instead, we can output our logs to a file&lt;/p&gt;
&lt;p&gt;A little &lt;code&gt;log&lt;/code&gt; function will do that:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;appendFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;contents&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; logMessage&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contents &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;string&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contents &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(contents)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; appendFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./log&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; logMessage &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So this will output the logs to a file called &lt;code&gt;log&lt;/code&gt; and can be super useful to debug/inspect any issues that come up&lt;/p&gt;
&lt;p&gt;Now, to receive a message we can listen to the &lt;code&gt;data&lt;/code&gt; even on &lt;code&gt;stdin&lt;/code&gt; and respond by logging on &lt;code&gt;stdout&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;initialize&lt;/code&gt; message expects a response with some basic information about the language server. Reading this message and responding can be done as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;stdout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;stdin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;process&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;appendFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;contents&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; logMessage&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contents &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;string&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contents &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(contents)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; appendFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./log&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; logMessage &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// listen to the `data` event on `stdin` returns a `Buffer`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;stdin.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;buff&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // convert the buffer into lines&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; message&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; buff.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;().&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;split&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\r\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // get the message content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; message[message.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // parse the message content into a request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; request&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(content)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // log the request to a file for later use&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(request)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (message.method &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!==&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;initialize&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // currently we only support the initialize message&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Unsupported message &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; message.method)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // respond with a JSON RPC message&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; result&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    jsonrpc: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // reference the ID of the request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    id: request.id,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // the result depends on the type of message being responded to&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    result: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      capabilities: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;        // we can add any functionality we want to support here as per the spec&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      serverInfo: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example-lsp&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        version: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.0.1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // create the Content-Length header&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Buffer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;byteLength&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; header&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `Content-Length: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // join the header and message into a response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;header&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\r\n\r\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;result&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // send the response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  stdout.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;write&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that the above example assumes that the entire message is received completely at once - there is no actual guarantee of this but it&amp;#39;s retained here for the sake of simplicity&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the basic flow for building a language server. Listening to events from some input, often &lt;code&gt;stdin/stdout&lt;/code&gt; and responding to it using JSON RPC. The types of messages that can be received along with the expected response or behavior is all outlined in &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/&quot; &gt;the LSP Specification&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Complete Example&lt;/h2&gt;
&lt;p&gt;A more complete example showing the handling of multiple messages can be seen below:&lt;/p&gt;
&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;lsp-example/package.json&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;json&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example-lsp&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;version&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;1.0.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;license&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;MIT&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;bin&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;./cli.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;  &amp;quot;devDependencies&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;    &amp;quot;@types/node&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;^22.13.13&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;figure class=&quot;snippet&quot; &gt;&lt;figcaption&gt;lsp-example/cli.js&lt;/figcaption&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;#!/usr/bin/env node&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// @ts-check&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;appendFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;fs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; { &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;stdout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;stdin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; } &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; require&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;process&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;contents&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; logMessage&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; typeof&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contents &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;#39;string&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ?&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; contents &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(contents)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; appendFileSync&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;./log&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; logMessage &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;LSP Started&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Received&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; parts&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; message.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;split&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\r\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; body&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(parts[parts.&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; body&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;result&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    jsonrpc: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;2.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    id: message.id,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    result,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; METHOD_NOT_FOUND&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;32601&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handleMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; isNotification&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; message.id &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;===&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (isNotification) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    // Notifications don&amp;#39;t require a response&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`Not responding to notification ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;method&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (message.method) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;initialize&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        capabilities: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          codeActionProvider: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          executeCommandProvider: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;            &amp;quot;commands&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: [&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;_example.doSomethingCool&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        serverInfo: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;example-lsp&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          version: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;0.0.1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;textDocument/codeAction&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message, [{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        title: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Do something cool&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        kind: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;quickfix&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        command: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;_example.doSomethingCool&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      }])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    default&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;      return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;undefined&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        code: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;METHOD_NOT_FOUND&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        message: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;`Requested method not found in handler ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;message&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;method&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sendResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;result&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(result)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; length&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; Buffer.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;byteLength&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(content, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `Content-Length: ${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;length&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\r\n\r\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;${&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Sending&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  stdout.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;write&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;stdin.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;d&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; message&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parseMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(d.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toString&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; response&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; handleMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(message)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (response) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    sendResponse&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(response)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;process.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;on&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;exit&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;LSP process terminated&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/figure&gt;&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot; &gt;Language Server Protocol Specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@malintha1996/understanding-the-language-server-protocol-5c0ba3ac83d2&quot; &gt;Understanding the Language Server Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Xo5VXTRoL6Q&quot; &gt;Building a Language Server from Scratch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/microsoft/vscode-languageserver-node&quot; &gt;VSCode Language Server Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/microsoft/vscode-extension-samples/tree/main/lsp-sample&quot; &gt;VSCode LSP Sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Scan based regex composition</title><link>https://nabeelvalley.co.za/blog/2025/27-03/regex-composition.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/27-03/regex-composition.html</guid><description>A simplified approach to complex text replacements</description><pubDate>Thu, 27 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Scan based regex composition&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Recently I needed a regex to camel-case some text, this sounds simple enough at first glance but since I had some very specific stylistic requirements it started to get more and more complex and the regex became pretty unwieldy &lt;/p&gt;
&lt;p&gt;A colleague suggested the following function to get the job done:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; normalize&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; str.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;/(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[a-z]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[A-Z]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;$1-$2&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, this works on simple examples like:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Hello-World&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;helloThereBob&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// hello-There-Bob&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;But it fails on more complex cases such as when we have numbers or when a word is all caps (abbreviations/initialisms?) such as these&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;URLParser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// URLParser, i want URL-Parser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Text1Parser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Text1Parser, i want Text-1-Parser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;MyURLExample1ForProgramX&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// My-URLExample1For-Program-X, i want My-URL-Example-1-For-Program-X&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;After a lot of playing around I couldn&amp;#39;t find a simple regex that let me do what I wanted. I did however like the idea of scanning across a string to make very specific, usually one or two character replacements. I liked the idea that different parts of the regex could be named and applied, using this idea - I thought we could have small regexes that do really simple things, such as:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; replacement&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `$1-$2`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; aB&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[a-z]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[A-Z]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; // aB -&amp;gt; a-B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; ABc&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[A-Z]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;[A-Z][a-z]&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; // A-Bc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; wd&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\w&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; // a1 -&amp;gt; a-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; dw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; /(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;\w&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;g&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; // 1a -&amp;gt; 1-a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Now, these small scanners work at the 2-3 letter pattern size and let us perform surgical replacements, scanning across text and applying a replacement on small subsets of a string.&lt;/p&gt;
&lt;p&gt;Something like looking for a pattern in &lt;code&gt;URLParser&lt;/code&gt; for a set of smaller patterns like: &lt;code&gt;UR&lt;/code&gt;, &lt;code&gt;RL&lt;/code&gt;,&lt;code&gt;LP&lt;/code&gt;, &lt;code&gt;Pa&lt;/code&gt;, &lt;code&gt;ar&lt;/code&gt;, &lt;code&gt;rs&lt;/code&gt;, &lt;code&gt;se&lt;/code&gt;, and &lt;code&gt;er&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;This takes away the global concern of the regex and lets us think distinctly about the different subproblems. Applying these sub-solutions is also easy:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; normalize&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	str.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(aB, replacement)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	   .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(ABc, replacement)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	   .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(wd, replacement)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	   .&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;replace&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dw, replacement)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Testing this with the examples that failed earlier we see the following result:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;js&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Hello-World&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;URLParser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// URL-Parser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Text1Parser&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// Text-1-Parser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;normalize&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;MyURLExample1ForProgramX&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// My-URL-Example-1-For-Program-X&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And that&amp;#39;s basically what I want.&lt;/p&gt;
&lt;p&gt;The above solution shows us a general approach that can be used for building complex replacement structures. It is possible that it would be less efficient than a big complicated regex but I think where possible, this solution allows us to incrementally build and add functionality to regex-based solutions in a way that&amp;#39;s much easier to understand and modify than one-shot regexes tend to be&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lastly, a quick note - the name of this post can probably use some work, the closest thing to this pattern that I can find is &lt;a href=&quot;https://martinfowler.com/bliki/ComposedRegex.html&quot; &gt;Composed Regex by Martin Fowler&lt;/a&gt; which breaks regexes down into smaller parts in order to create a bigger regex&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Problems are better left solved</title><link>https://nabeelvalley.co.za/blog/2025/27-08/problems-are-better-left-solved.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/27-08/problems-are-better-left-solved.html</guid><description>Some thoughts on Go</description><pubDate>Wed, 27 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Problems are better left solved&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;&lt;img src=&quot;/content/projects/dejavu.gif&quot; alt=&quot;dejavu cli usage&quot; &gt;&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t enjoy writing Go. I like languages that challenge me, that make me think about processes, model the domain, and force me to be as complete as possible in my thinking. Go does none of this, but it seems to be the only language I program in lately&lt;/p&gt;
&lt;p&gt;Corporate work, as you might imagine (or, more likely, understand to your core), is not fun. It tends to be a lot of talking around problems instead of solving them, and solving around metrics instead of people&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve been struggling to find ways to add value and have been moving my focus around a bit. Between people throwing AI at anything that will stick and pushing for MORE OUTPUT constantly, there&amp;#39;s little room to make a meaningful impact. Most people are flooded with work and don&amp;#39;t really have time to talk about big problems or to find solutions to anything real&lt;/p&gt;
&lt;p&gt;I think small frustrations are often undervalued - particularly ones that people think are unique to them. These tend to be quite easy to solve, but since they&amp;#39;re perceived as isolated problems we don&amp;#39;t really bother to solve them&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve recently noticed a lot of issues popping up where the solution is &amp;quot;read the documentation&amp;quot;&lt;/p&gt;
&lt;p&gt;It&amp;#39;s something we emphasise a lot as technical people. What always falls by the wayside however, is what documentation? Where do I find it? How do I know what I&amp;#39;m doing is even documented - why would it be if it&amp;#39;s a problem I&amp;#39;m only experiencing?&lt;/p&gt;
&lt;p&gt;At the moment I&amp;#39;m on a team that develops and supports libraries that other teams use. A large chunk of this involves working with developers to help understand where and how to integrate with our libraries&lt;/p&gt;
&lt;p&gt;When working with lots of developers you start to notice patterns. In the way people work, how they use their tools, and the types of issues they run into&lt;/p&gt;
&lt;p&gt;Developers in some team may struggle with a bug for days, when across the hall, another team knows the fix&lt;/p&gt;
&lt;p&gt;Sure, community channels help, but if the message isn&amp;#39;t phrased in a certain way or if the right person doesn&amp;#39;t see it then it&amp;#39;s of no use&lt;/p&gt;
&lt;p&gt;Often, we&amp;#39;ve documented the solutions, but no one seems to know.&lt;/p&gt;
&lt;p&gt;The problem isn&amp;#39;t that developers don&amp;#39;t read the documentation, it&amp;#39;s that we&amp;#39;ve failed to show it to them at the right time and in the right place&lt;/p&gt;
&lt;p&gt;Usually when developers run into an issue, the first place they look is their terminal - do I see any errors? Is there a weird warning of some kind?&lt;/p&gt;
&lt;p&gt;I think this space that occupies so much of our time and energy is underutilized, searching for error messages online is hit or miss, and good luck if it&amp;#39;s something to do with your company&amp;#39;s specific setup&lt;/p&gt;
&lt;p&gt;Well, computers read faster than people. I had an idea that I could tie the terminal and documentation together - so I wrote an app that does just that&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/sftsrv/dejavu&quot; &gt;Déjà vu&lt;/a&gt; is a little app that scans the output of terminal commands in real time to find documentation that may be relevant for issues that developers are facing&lt;/p&gt;
&lt;p&gt;It works using existing documentation and is a little program I put together in a few hours using Go&lt;/p&gt;
&lt;p&gt;So I&amp;#39;m not a fan of Go.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve been writing a lot of it recently though. It&amp;#39;s easy to set up, has a great ecosystem, is pretty fast, and it just works. Things that would take days to solve in other languages are an evening of work with Go&lt;/p&gt;
&lt;p&gt;Recently, the problems I&amp;#39;ve been trying to solve have revolved around other people. Hacky scripts and complex shell setups are not things they have. Solutions need to be free standing and &amp;quot;just work&amp;quot;&lt;/p&gt;
&lt;p&gt;When it comes to other people, I tend to prioritize getting a solution quickly. Small solutions become less valuable as time passes, and people become more annoyed too.&lt;/p&gt;
&lt;p&gt;Iterating across people is a lot slower than iterating with yourself, so being able to start conversations early is important.&lt;/p&gt;
&lt;p&gt;All of this basically to say - Go helps me solve problems quickly. So what if I don&amp;#39;t like it.&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Web Authentication API</title><link>https://nabeelvalley.co.za/blog/2025/29-07/web-authentication-api.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/29-07/web-authentication-api.html</guid><description>Simple example of the Web Authentication API in action</description><pubDate>Tue, 29 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Web Authentication API&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;The Web Authentication API is a public/private key based authentication mechanism that is built into modern browsers and enables us to easily develop authentication solutions on the web&lt;/p&gt;
&lt;p&gt;It consists of a few simple APIs, namely &lt;code&gt;navigator.credentials.get&lt;/code&gt; and &lt;code&gt;navigatior.credentials.create&lt;/code&gt;. A simple example that uses these APIs can be seen below:&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;div id=&quot;authn-example&quot; &gt;&lt;/div&gt;&lt;script&gt;
let creds;

const createButton = document.createElement(&#39;button&#39;);
createButton.innerText = &quot;Create Account&quot;;
createButton.onclick = async () =&gt; {
    const newCreds = await createCredentials();
    alert(&quot;Created credentials are&quot; + JSON.stringify(newCreds));
    creds = newCreds;
};

const loginButton = document.createElement(&#39;button&#39;);
loginButton.innerText = &quot;Log In&quot;;
loginButton.onclick = async () =&gt; {
    if (!creds) {
        throw new Error(&quot;Credentials not created&quot;);
    }
    const gotCreds = await getCredentials(creds.rawId);
    alert(&quot;Loaded credentials are&quot; + JSON.stringify(gotCreds));
};

document.querySelector(&#39;#authn-example&#39;).appendChild(createButton);
document.querySelector(&#39;#authn-example&#39;).appendChild(loginButton);

function getCredentials(id) {
    return navigator.credentials.get({
        publicKey: {
            challenge: new Uint8Array([117, 61, 252, 231, 191, 241 /* … */]),
            rpId: window.location.host,
            allowCredentials: [
                {
                    id,
                    type: &quot;public-key&quot;,
                },
            ],
            userVerification: &quot;required&quot;,
        }
    });
}

function createCredentials() {
    return navigator.credentials.create({
        publicKey: {
            challenge: new Uint8Array([117, 61, 252, 231, 191, 241 /* … */]),
            rp: { id: window.location.host, name: &quot;Nabeel Credential Testing&quot; },
            user: {
                id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]),
                name: &quot;jamiedoe&quot;,
                displayName: &quot;Jamie Doe&quot;,
            },
            pubKeyCredParams: [{ type: &quot;public-key&quot;, alg: -7 }],
        },
    });
}

function sleep(ms = 2000) {
    return new Promise((res) =&gt; setTimeout(res, ms));
}
&lt;/script&gt;&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;And the code that implements the above can be seen as follows&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;ts&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; creds&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Credential&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; createButton&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;button&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;createButton.innerText &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Create Account&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;createButton.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;onclick&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; newCreds&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createCredentials&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  alert&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Created credentials are&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(newCreds))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  creds &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; newCreds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; loginButton&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;createElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;button&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;loginButton.innerText &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Log In&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;loginButton.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;onclick&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; async&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;creds) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Credentials not created&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  const&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; gotCreds&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; await&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getCredentials&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(creds.rawId)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  alert&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Loaded credentials are&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; JSON&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;stringify&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(gotCreds))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;HTMLDivElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;#authn-example&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(createButton)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;document.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;HTMLDivElement&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;#39;#authn-example&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(loginButton)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; getCredentials&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;id&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; BufferSource&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; navigator.credentials.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;get&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    publicKey: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      challenge: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Uint8Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;117&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;61&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;252&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;231&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;191&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;241&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; /* … */&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      rpId: window.location.host,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      allowCredentials: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          id,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;          type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;public-key&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      userVerification: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;required&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createCredentials&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; navigator.credentials.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;create&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    publicKey: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      challenge: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Uint8Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;117&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;61&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;252&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;231&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;191&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;241&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; /* … */&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      rp: { id: window.location.host, name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Nabeel Credential Testing&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      user: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        id: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;new&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Uint8Array&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;79&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;252&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;83&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;72&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;214&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;7&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;89&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;26&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        name: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;jamiedoe&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        displayName: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Jamie Doe&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      pubKeyCredParams: [{ type: &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;public-key&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, alg: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;7&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;function&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ms&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 2000&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; new&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;((&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;res&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; setTimeout&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(res, ms))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Week 35, Documentation matters</title><link>https://nabeelvalley.co.za/blog/2025/31-08/week-35-trying-this-out-again.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2025/31-08/week-35-trying-this-out-again.html</guid><description>Markdown, Golang, SwiftUI, and Corporates</description><pubDate>Sun, 31 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Week 35, Documentation matters&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Trying to get back into some regular blogging rhythym since if I don&amp;#39;t pay attention multiple months pass by between posts&lt;/p&gt;
&lt;h2&gt;What I&amp;#39;m working on&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Wrote a bit about the &lt;a href=&quot;/blog/2025/27-08/problems-are-better-left-solved&quot; &gt;impact Go has had&lt;/a&gt; on how I write software recently&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wrapped up work on &lt;a href=&quot;https://github.com/sftsrv/dejavu&quot; &gt;Déjà vu&lt;/a&gt; which is a command line app to bring documentation to developers when they need it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learning SwiftUI, basically watching pretty much everything &lt;a href=&quot;https://www.youtube.com/@twostraws&quot; &gt;Paul Hudson&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/@SwiftyPlace&quot; &gt;Karin Prater&lt;/a&gt; have made&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What I found&lt;/h2&gt;
&lt;h3&gt;Mask&lt;/h3&gt;
&lt;p&gt;Something I spotted a while back and kind of just skimmed over, &lt;a href=&quot;https://github.com/jacobdeichert/mask&quot; &gt;mask&lt;/a&gt; is a task runner (like &lt;code&gt;make&lt;/code&gt;) that uses markdown for documenting commands. It seems great and is something I&amp;#39;d like to play around with in future&lt;/p&gt;
&lt;h3&gt;Gauge&lt;/h3&gt;
&lt;p&gt;On the topic of markdown, &lt;a href=&quot;https://gauge.org/&quot; &gt;Gauge&lt;/a&gt; uses markdown docs to specify test specifications that are then backed by framework/language specific implementations to actually run those specs&lt;/p&gt;
&lt;h3&gt;Pages CMS&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://pagescms.org/&quot; &gt;Pages CMS&lt;/a&gt; is a content management system I&amp;#39;ve been using for a while that provides a nice UI for working with markdown and JSON content and is actually what I&amp;#39;m writing this post on right now&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>In Color</title><link>https://nabeelvalley.co.za/blog/2026/01-08/in-color.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/01-08/in-color.html</guid><description>Some fisheye pictures from Amsterdam Pride</description><pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;In Color&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I&amp;#39;ve been grinding like mad on the &lt;a href=&quot;https://github.com/sftsrv/charge&quot; &gt;static site library&lt;/a&gt; I&amp;#39;m building. It&amp;#39;s wrapping up at last and seems to have all the functionality I need for my website currently&lt;sup id=&quot;footnote-reference-1&quot; class=&quot;footnote-reference&quot; &gt;&lt;a href=&quot;#footnote-target-1&quot; &gt;1&lt;/a&gt;&lt;/sup&gt;. It was a pretty big detour from actually working on the site but a worthwhile one&lt;/p&gt;
&lt;p&gt;But that&amp;#39;s not what this post is about.&lt;/p&gt;
&lt;p&gt;This weekend I, on a whim, decided to pop around and take some pictures at the &lt;a href=&quot;https://pride.amsterdam/worldpride/&quot; &gt;World Pride Canal Parade&lt;/a&gt;. I had my &lt;a href=&quot;https://www.ttartisan.com/?aps-c-lenses/72.html&quot; &gt;TTArtisan 7.5mm f/2 lens&lt;/a&gt; and sort of committed to the bit &lt;sup id=&quot;footnote-reference-2&quot; class=&quot;footnote-reference&quot; &gt;&lt;a href=&quot;#footnote-target-2&quot; &gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Of course, these pictures are in color (as much as I wanted to make them not be)&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Artwork-that-says-&amp;quot;You-do-you-or-whoever-the-__-you-want&amp;quot;.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Artwork that says &amp;quot;You do you or whoever the __ you want&amp;quot;&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Artwork%20that%20says%20%22You%20do%20you%20or%20whoever%20the%20__%20you%20want%22.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Canal-with-buildings-alongside.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Canal with buildings alongside&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Canal%20with%20buildings%20alongside.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Couple-standing-under-bridge.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Couple standing under bridge&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Couple%20standing%20under%20bridge.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-going-down-escalator.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People going down escalator&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20going%20down%20escalator.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-laughing.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People laughing&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20laughing.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-sitting-on-edge-of-canal-looking-at-boats.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People sitting on edge of canal looking at boats&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20sitting%20on%20edge%20of%20canal%20looking%20at%20boats.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-sitting-on-top-of-subway-enterance.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People sitting on top of subway enterance&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20sitting%20on%20top%20of%20subway%20enterance.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-sitting-outside-of-appartment-windows.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People sitting outside of appartment windows&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20sitting%20outside%20of%20appartment%20windows.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-standing-on-balcony-with-pride-flag-hanging-off.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People standing on balcony with pride flag hanging off&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20standing%20on%20balcony%20with%20pride%20flag%20hanging%20off.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-standing-on-boat-with-pride-flag-hanging-off-front.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People standing on boat with pride flag hanging off front&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20standing%20on%20boat%20with%20pride%20flag%20hanging%20off%20front.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-standing-on-bridge-overlooking-boats-on-canal.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People standing on bridge overlooking boats on canal&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20standing%20on%20bridge%20overlooking%20boats%20on%20canal.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-standing-overlooking-canal.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People standing overlooking canal&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20standing%20overlooking%20canal.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---People-waving-pride-flags-in-front-of-canal.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - People waving pride flags in front of canal&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20People%20waving%20pride%20flags%20in%20front%20of%20canal.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-covering-their-eyes-to-block-the-sun.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person covering their eyes to block the sun&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20covering%20their%20eyes%20to%20block%20the%20sun.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-pointing-at-sign-saying-&amp;quot;I&amp;#39;m-sorry-I-invented-capitalism&amp;quot;.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person pointing at sign saying &amp;quot;I&amp;#39;m sorry I invented capitalism&amp;quot;&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20pointing%20at%20sign%20saying%20%22I&amp;#39;m%20sorry%20I%20invented%20capitalism%22.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-sitting-on-wall-next-to-reflective-building.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person sitting on wall next to reflective building&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20sitting%20on%20wall%20next%20to%20reflective%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-taking-a-picture-of-a-rainbow-star-on-the-canal.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person taking a picture of a rainbow star on the canal&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20taking%20a%20picture%20of%20a%20rainbow%20star%20on%20the%20canal.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-waving-Ace-flag.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person waving Ace flag&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20waving%20Ace%20flag.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-waving-a-giant-rainbow-fan.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person waving a giant rainbow fan&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20waving%20a%20giant%20rainbow%20fan.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-wearing-pink-on-bicycle.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person wearing pink on bicycle&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20wearing%20pink%20on%20bicycle.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-with-big-hat-posing.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person with big hat posing&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20with%20big%20hat%20posing.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-with-orange-polka-dot-shirt-waving-pink-fan.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person with orange polka dot shirt waving pink fan&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20with%20orange%20polka%20dot%20shirt%20waving%20pink%20fan.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Person-with-rainbow-fan-sitting-on-side-of-the-IJ.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Person with rainbow fan sitting on side of the IJ&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Person%20with%20rainbow%20fan%20sitting%20on%20side%20of%20the%20IJ.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Police-officer-staring-up-at-something.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Police officer staring up at something&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Police%20officer%20staring%20up%20at%20something.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-08-01---world-pride/2026-08-01---xt7.5---color---NL---Amsterdam---Walking-through-crowd.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-08-01 - xt7.5 - color - NL - Amsterdam - Walking through crowd&quot; src=&quot;/optimized-images/content/photography/blog/2026-08-01%20-%20world%20pride/2026-08-01%20-%20xt7.5%20-%20color%20-%20NL%20-%20Amsterdam%20-%20Walking%20through%20crowd.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;p&gt;&lt;span&gt;&lt;a id=&quot;footnote-target-1&quot; href=&quot;#footnote-reference-1&quot; class=&quot;footnote-target&quot; &gt;1&lt;/a&gt;:&lt;/span&gt; I also spent like half of last week sorting the pictures on my site in preparation for the new photo gallery I want to implement. Though it feels like I&amp;#39;m &lt;em&gt;so&lt;/em&gt; far from getting to that. This entire thing is a huge undertaking and I really hope that my solution ends up being something I get a lot of use out of. There&amp;#39;s already a few sites I want to move over to it so hopefully that&amp;#39;s not too tiring. Because I still have to complete my &lt;a href=&quot;/blog/2026/08-07/website-revision-7-part-0&quot; &gt;website upgrade blog series&lt;/a&gt; so it&amp;#39;s going to be a while&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a id=&quot;footnote-target-2&quot; href=&quot;#footnote-reference-2&quot; class=&quot;footnote-target&quot; &gt;2&lt;/a&gt;:&lt;/span&gt; I just got it about a week ago and I&amp;#39;m still like fisheye lenses are crazy dude&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Editing Text in-stream</title><link>https://nabeelvalley.co.za/blog/2026/02-06/in-stream-text-editor.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/02-06/in-stream-text-editor.html</guid><description>A small helper to more easily edit files mid-stream</description><pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Editing Text in-stream&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I&amp;#39;ve recently been finding &lt;a href=&quot;https://www.gnu.org/software/sed/&quot; &gt;&lt;code&gt;sed&lt;/code&gt;&lt;/a&gt; really handy but sometimes I want to edit something bigger in-stream - maybe just to make some small manual fixes before dumping dumping a string out to some other command. I&amp;#39;ve been using &lt;code&gt;pbcopy&lt;/code&gt; a lot for this kind of thing but I wanted a neater way to do it, and here&amp;#39;s my solution&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# Edit file in stream by writing to a file, opening the editor and printing back to stdout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# File will be stored in a temp file in the current directory and deleted once edit is complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# Example edit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;#  &amp;gt; bat package.json | f edit-stream json | save updated.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;def&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;f edit-stream&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  # extension to use when writing the file. Useful to get syntax highlighting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  ext:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;txt&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  # prefix to be used for tempfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  prefix:&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; string&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;ed-&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  # if the temp file should be retained after editing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  --keep,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  ] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; f&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; $&amp;quot;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$prefix&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)(date now | format date &amp;#39;%+&amp;#39;).(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$ext&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  $in &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; save&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  nu&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; -c&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; $&amp;quot;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$env&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;.EDITOR) (&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$f&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  if&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; not&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $keep &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    bat&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;alias&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; fed&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; f&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; edit-stream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a &lt;a href=&quot;https://www.nushell.sh/&quot; &gt;Nushell&lt;/a&gt; function which makes it possible to do just that, and in practice could look something like this:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;bat&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; package.json&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; # open a file using `bat`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; f&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; edit-stream&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; json&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; # open the file in the configured $EDITOR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; save&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; updated.json&lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt; # save this to some other output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;By default this also uses &lt;a href=&quot;https://github.com/sharkdp/bat&quot; &gt;&lt;code&gt;bat&lt;/code&gt;&lt;/a&gt; to print the output to give syntax highlighting to users but will also pass the plain text on if being passed to another command&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Zig - Bus error at address and memory management</title><link>https://nabeelvalley.co.za/blog/2026/06-06/zig-memory-allocation.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/06-06/zig-memory-allocation.html</guid><description>Challenges with memory management in Zig</description><pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Zig - Bus error at address and memory management&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Assumed audience: People learning the Zig programming language&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note that since Zig is in pretty active development this error message differs quite a bit between versions though the general idea should apply. For context though I&amp;#39;m using &lt;code&gt;zig v0.17.0-dev.690+c5a61e899&lt;/code&gt; which is the latest &lt;code&gt;master&lt;/code&gt; and is not yet a stable release&lt;/p&gt;
&lt;h2&gt;Error&lt;/h2&gt;
&lt;p&gt;So I&amp;#39;ve been learning &lt;a href=&quot;https://ziglang.org/&quot; &gt;Zig&lt;/a&gt; since about yesterday and since then I&amp;#39;ve started writing a scripting language. During my test runs I kept running into this error:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Bus error at address 0x104f6fa5d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /zig/bin/lib/compiler_rt.zig:663:14: 0x104f3b9c8 in memset (compiler_rt)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /zig/zig/lib/std/mem/Allocator.zig:450:5: 0x104e46c93 in free__anon_10187 (test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           @memset(bytes, undefined);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /repo/src/root.zig:262:17: 0x104f2ff9b in deinit (test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;               gpa.free(self.content);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;                       ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /repo/src/root.zig:281:26: 0x104f2dfff in test.Bus error at address repro (test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           defer expected.deinit(gpa);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;                                ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /zig/zig/lib/compiler/test_runner.zig:143:68: 0x104f0860b in mainServer (test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;                       const status: TestResults.Status = if (test_fn.func()) |v| s: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;                                                                          ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /zig/zig/lib/compiler/test_runner.zig:71:26: 0x104f08c87 in main (test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;               return mainServer(init) catch |err| panic(&amp;quot;internal test runner failure: {t}&amp;quot;, .{err});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;                                ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       /zig/zig/lib/std/start.zig:740:88: 0x104f06ad7 in callMain (test)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;           if (fn_info.param_types[0].? == std.process.Init.Minimal) return wrapMain(root.main(.{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;                                                                                              ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;       ???:?:?: 0x195fe5d53 in start (/usr/lib/dyld)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Explanation&lt;/h2&gt;
&lt;p&gt;The message is quite cryptic: &amp;quot;Bus error at address&amp;quot; and just points to some call to &lt;code&gt;free&lt;/code&gt; that I&amp;#39;ve made. I have no idea why that was the issue and assumed the issue was me messing around with my memory management&lt;/p&gt;
&lt;p&gt;I reimplemented the solution and tried multiple fixes and couldn&amp;#39;t get the bug to go away, so I started reading everything I could understand about Zig memory allocation and some different management strategies&lt;/p&gt;
&lt;p&gt;The comment that led me to some insight was from &lt;a href=&quot;https://ziggit.dev/t/panic-invalid-free-when-freeing-a-structs-allocated-memory/8280&quot; &gt;a question about invalid frees&lt;/a&gt; where a commenter says &amp;quot;Invalid free means that you are trying to free data that was never allocated with that allocator.&amp;quot; - really right in front my face. And then I though - hmm, where am I allocating memory that I am using a different allocator for. Well - nowhere.&lt;/p&gt;
&lt;p&gt;But then I thought - what if I was trying to free something that I didn&amp;#39;t allocate memory for - which led me to a string - which is a compile time constant, and so isn&amp;#39;t allocated on the heap.&lt;/p&gt;
&lt;p&gt;Turned out that the string I had to verify my implementation in my test code was being freed by implementation&amp;#39;s cleanup code. The issue was the test. I know - incredibly silly&lt;/p&gt;
&lt;p&gt;The takeaway however is - If you see the error above, make sure you&amp;#39;re only freeing memory that you&amp;#39;ve allocated&lt;/p&gt;
&lt;h2&gt;Reproduction&lt;/h2&gt;
&lt;p&gt;For the sake of completeness and having something more than just a big error dump - here&amp;#39;s a reproduction I made:&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a small function that creates a struct called &lt;code&gt;Data&lt;/code&gt; with a &lt;code&gt;content&lt;/code&gt; property and a &lt;code&gt;deinit&lt;/code&gt; method for freeing any associated memory.&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;zig&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;    content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: []&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; deinit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;self&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Allocator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;void&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;				// just frees the content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;        gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;free&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;self&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Allocator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;input&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: []&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;const&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    var&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; buf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;std&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ArrayList&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;u8&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; .&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;empty&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// iterate through a string and add each character twice to a buffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// for funsies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;input&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;c&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        try&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; buf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;c&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;        try&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; buf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;c&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// convert the ArrayList to a Slice.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// this frees the ArrayList and returns a newly allocated []u8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// whoever get&amp;#39;s content needs to free it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		const&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; try&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; buf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;toOwnedSlice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// create a data struct with the resulting content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// this can be freed using the Data.deinit method&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{ .&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; content&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In my test, I had this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;zig&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;test&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Bus error at address repro&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    const&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; gpa&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; std&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;testing&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// create an expected Data instance with content as a constant&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    var&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; expected&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Data&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{ .&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;content&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;hheelllloo&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// this below deinit call is bad and was causing the above error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    defer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; expected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;deinit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;); &lt;/span&gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// &amp;lt;- this line should be removed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// we don&amp;#39;t need to free expected.content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// trying to free this will lead to an error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// create the actual Data instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    var&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; actual&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; try&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; createData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;		// free the actual data using the Data.deinit function defined above&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    defer&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; actual&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;deinit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;gpa&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    try&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; std&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;testing&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;expectEqualDeep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;expected&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;actual&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Removing the call to my struct&amp;#39;s &lt;code&gt;deinit&lt;/code&gt; method fixed the error&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;In case you skipped to the end to find the answer, as I mentioned above - ensure that you&amp;#39;re only freeing memory that you allocated directly - and double check and test structs that you&amp;#39;re freeing.&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>r7.0 - Housekeeping</title><link>https://nabeelvalley.co.za/blog/2026/08-07/website-revision-7-part-0.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/08-07/website-revision-7-part-0.html</guid><description>Some cleanup before the new site redesign can begin</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;r7.0 - Housekeeping&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;This is the 0th post in series about my website redesign, I&amp;#39;ll add links to the other parts here as they become available&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Context&lt;/h2&gt;
&lt;p&gt;My website has been around for quite some time. Having a space on the internet is really important to me and over the years it&amp;#39;s been home to countless experiments and attempts at self expression&lt;/p&gt;
&lt;p&gt;As such, what I need from this website is constantly evolving. Converging in some ways, diverging in others&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve build support for numerous data formats, abandoned or restructured others, and standardized along the way. Walking through flexibility, expression, and maintainability&lt;/p&gt;
&lt;p&gt;Through the previous iterations of this website I&amp;#39;ve been mostly concerned with adding new things. Features, data, flair. But through this constant upward climb, the weight I&amp;#39;m carrying becomes ever more burdensome&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve been meaning to do a redesign for a few months now at least. The previous version of my site had been active since 2023. It was built with &lt;a href=&quot;https://astro.build/&quot; &gt;Astro&lt;/a&gt; which is a JavaScript framework for building static sites. Astro&amp;#39;s biggest selling point being its &lt;a href=&quot;https://docs.astro.build/en/concepts/islands/&quot; &gt;islands architecture&lt;/a&gt; that lets you opt into using different libraries or frameworks as you need. You can drop in a &lt;a href=&quot;https://react.dev/&quot; &gt;React&lt;/a&gt; component for your search box, and let authors write content in &lt;a href=&quot;https://mdxjs.com/&quot; &gt;MDX&lt;/a&gt; that embeds any components from any myriad of other frameworks&lt;/p&gt;
&lt;p&gt;Over the years I&amp;#39;ve grown weary of tools that do much more than you need. The problem with doing too much is that it is often at the expense of doing those things well. Along with the ability to do lots of stuff, you also get the downside of doing all those things&lt;/p&gt;
&lt;p&gt;For example, deep MDX integration makes it difficult to author content anywhere other than a code editor, or complex build processes make it difficult to fix issues that come up when you inevitably need to update some random dependency&lt;/p&gt;
&lt;h2&gt;Taking Account&lt;/h2&gt;
&lt;p&gt;The primary challenges of updating my website come from some complex content support I built quite early, and a few Astro components that do server-side stuff that I built along the way&lt;/p&gt;
&lt;p&gt;Some formats I don&amp;#39;t want to support anymore are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;MDX - Between editor syntax highlighting messiness from using every framework as once and the complexity it adds to the build process this is something I don&amp;#39;t want anymore&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jupyter.org/&quot; &gt;Jupyter Notebooks&lt;/a&gt; - I used to do a lot of python programming when I just started out and this was a pretty sizable chunk of my notes but that hasn&amp;#39;t been the case for years. Jupyter notebooks are also just not something that most static site generators support out of the box. So I&amp;#39;ve always have had to implement my own parser and renderer for them which just isn&amp;#39;t what I want to spend my time doing&lt;/li&gt;
&lt;li&gt;Web frameworks in general - I&amp;#39;ve always had some framework to carry along, this always comes with a lot of build complexity and a mountain of dependencies. I just don&amp;#39;t want to deal with frameworks if I don&amp;#39;t have to - and in this case I don&amp;#39;t have. For cases where I need some interactivity I&amp;#39;m going to stick to plain old &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_components&quot; &gt;web components&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Planning Ahead&lt;/h2&gt;
&lt;p&gt;Before I could just delete everything though, I needed to figure out what I want my new site to have and come up with a plan for cleaning up my content&lt;/p&gt;
&lt;p&gt;I skimmed my codebase and found a few categories of stuff that needed to be migrated and came up with a plan accordingly:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Jupyter Notebooks - I&amp;#39;ll adapt my script that renders them to HTML to instead output Markdown versions of the notebook files that will work as-is with my site. Managing images would be a bit messy but it&amp;#39;s a relatively minor detail&lt;/li&gt;
&lt;li&gt;Client side components - These are either Astro or JSX. Depending on the component I&amp;#39;ll do one of the following:&lt;ol&gt;
&lt;li&gt;If I have an existing web-component, I&amp;#39;ll update all instances to use that - e.g. &lt;a href=&quot;/talks&quot; &gt;my presentation components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If it&amp;#39;s a simple Astro component that I want to keep I&amp;#39;ll rewrite it as a web component like - e.g. &lt;a href=&quot;/intro-to-shaders&quot; &gt;my shader renderer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If it&amp;#39;s a component that&amp;#39;s just used in a few places I&amp;#39;ll inline it where needed&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Server side components - These are the most complex and are used a lot. These will be discussed in a later blog post in this series&lt;/li&gt;
&lt;li&gt;Random JSON data for some pages - This should be relatively simple to handle and is mostly just &amp;quot;effort&amp;quot; so I&amp;#39;ll pick that up later and use hardcoded HTML for now&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Site Requirements&lt;/h2&gt;
&lt;p&gt;Based on an analysis of what I want to keep, the new site architecture has some hard requirements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Markdown support for pages&lt;/li&gt;
&lt;li&gt;Web component support &lt;ul&gt;
&lt;li&gt;For the sake of using TypeScript here, a compiler/bundler will also be needed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Server-side components of some kind&lt;/li&gt;
&lt;li&gt;Some dynamic routes - like the &lt;a href=&quot;/blog&quot; &gt;blog&lt;/a&gt; and &lt;a href=&quot;/docs&quot; &gt;docs&lt;/a&gt; index as well as &lt;a href=&quot;/feed/rss.xml&quot; &gt;RSS feed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;No dependency on frontend frameworks (more of an anti-requirement I guess)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I also really wanted to use &lt;a href=&quot;https://gleam.run/&quot; &gt;Gleam&lt;/a&gt; because I like it and would like to stress-test my functional programming abilities. A secondary goal of this project is to create a small library that I can use to create other sites&lt;/p&gt;
&lt;p&gt;Additionally, since I&amp;#39;ve been a bit more involved with web accessibility recently, I&amp;#39;m going pay attention to this on the new site and try to deliver the best experience I can&lt;/p&gt;
&lt;h2&gt;Next Up&lt;/h2&gt;
&lt;p&gt;Since this is the 0th part, that perhaps implies that there are other posts to come. My plan for this series is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Part 0 - Housekeeping (this post)&lt;/li&gt;
&lt;li&gt;Part 1 - Architecture&lt;/li&gt;
&lt;li&gt;Part 2 - Creating Pages&lt;/li&gt;
&lt;li&gt;Part 3 - Server Components&lt;/li&gt;
&lt;li&gt;Part 4 - A Library&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The site is currently live and is a little ahead of what we&amp;#39;ve talked about so far, so look around and have a peek at what&amp;#39;s to come&lt;/p&gt;
&lt;h2&gt;Closing&lt;/h2&gt;
&lt;p&gt;I don&amp;#39;t expect this site to last forever. Just as how its predecessors didn&amp;#39;t. I would however like to focus on decoupling some of the bits that make it possible so that I can upgrade them more iteratively&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t plan to have a giant all-features-at-once release. The new site will come up in pieces and it&amp;#39;s not a goal to ever have feature parity with the old version. I&amp;#39;d like to focus on having more well thought-out and interestingly designed features. And, well … that takes time&lt;/p&gt;
&lt;p&gt;Lastly a shout out to &lt;a href=&quot;https://bell.bz/&quot; &gt;Andy Bell&amp;#39;s&lt;/a&gt; personal site redesign &lt;a href=&quot;https://piccalil.li/projects/personal-site/&quot; &gt;series on Piccalilli&lt;/a&gt; which is the inspiration for this series&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Summer in Paris</title><link>https://nabeelvalley.co.za/blog/2026/10-07/summer-in-paris.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/10-07/summer-in-paris.html</guid><description>A lil day trip to Paris</description><pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Summer in Paris&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;We took a quick trip on the Eurostar to Paris on Monday and just hung out a bit. The most interesting thing we did was a visit to the &lt;a href=&quot;https://www.pinaultcollection.com/fr/boursedecommerce&quot; &gt;Bourse De Commerce&lt;/a&gt; which had &lt;a href=&quot;https://en.wikipedia.org/wiki/Fujiko_Nakaya&quot; &gt;Fujiko Nakaya&amp;#39;s&lt;/a&gt; Cloud installation in the main exhibition hall&lt;/p&gt;
&lt;p&gt;The experience was beautiful and eerie. Here&amp;#39;s a short video I made from inside the installation:&lt;/p&gt;
&lt;video controls=&quot;&quot; alt=&quot;2026-03-28 - Summer in Paris&quot; width=&quot;100%&quot; &gt;
  &lt;source src=&quot;/content/blog/2026/10-07/summer-in-paris.mov&quot; &gt;
&lt;/video&gt;&lt;p&gt;And of course, there are some pictures too:&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Building-in-distance-with-graffiti.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Building in distance with graffiti&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Building%20in%20distance%20with%20graffiti.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Chairs-in-mall.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Chairs in mall&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Chairs%20in%20mall.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Cloud-with-people-on-balcony.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Cloud with people on balcony&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Cloud%20with%20people%20on%20balcony.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Cloud-with-person-standing-in-front.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Cloud with person standing in front&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Cloud%20with%20person%20standing%20in%20front.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Door-with-stacks-of-newspaper-beside-it.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Door with stacks of newspaper beside it&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Door%20with%20stacks%20of%20newspaper%20beside%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Exhibit-Text---Fujiko-Nakaya,-Cloud.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Exhibit Text - Fujiko Nakaya, Cloud&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Exhibit%20Text%20-%20Fujiko%20Nakaya%2C%20Cloud.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Flag-outside-of-window.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Flag outside of window&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Flag%20outside%20of%20window.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Peolpe-taking-pictures-in-Cloud.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Peolpe taking pictures in Cloud&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Peolpe%20taking%20pictures%20in%20Cloud.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---People-in-shadows-in-Cloud.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - People in shadows in Cloud&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20People%20in%20shadows%20in%20Cloud.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---People-taking-photos-of-people-in-Cloud.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - People taking photos of people in Cloud&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20People%20taking%20photos%20of%20people%20in%20Cloud.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Person-standing-in-front-of-window-in-shadow.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Person standing in front of window in shadow&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Person%20standing%20in%20front%20of%20window%20in%20shadow.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Person-taking-picture-in-Cloud.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Person taking picture in Cloud&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Person%20taking%20picture%20in%20Cloud.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-06---summer-in-paris/2026-07-06---xt35---bw---FR---Paris---Summer-in-Paris---Person-taking-pictures-of-others-in-Cloud.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-06 - xt35 - bw - FR - Paris - Summer in Paris - Person taking pictures of others in Cloud&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-06%20-%20summer-in-paris/2026-07-06%20-%20xt35%20-%20bw%20-%20FR%20-%20Paris%20-%20Summer%20in%20Paris%20-%20Person%20taking%20pictures%20of%20others%20in%20Cloud.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>CSS Anchor Positioning</title><link>https://nabeelvalley.co.za/blog/2026/11-02/css-anchor-positioning.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/11-02/css-anchor-positioning.html</guid><description>Positining CSS elements and some other interesting CSS</description><pubDate>Wed, 11 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;CSS Anchor Positioning&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I was reading a pull request the other day and someone suggested the use of &lt;code&gt;position-anchor&lt;/code&gt; which was something I hadn&amp;#39;t seen before and so I thought I&amp;#39;d write something small about it&lt;/p&gt;
&lt;p&gt;In putting together this example, I came across a few interesting points that I wanted to talk about - but before getting into those, here&amp;#39;s a small example first&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;For the example we&amp;#39;ll use some HTML and CSS in order to place some content relative to some specific anchor. The result we see is that the &amp;quot;Content for Anchor N&amp;quot; is placed at the top right of the &amp;quot;Anchor N&amp;quot; element, but this could be many other placements or layouts as desired&lt;/p&gt;
&lt;section&gt;
  &lt;h3 class=&quot;anchor&quot; anchor-name=&quot;--anchor-1&quot; &gt;Anchor 1&lt;/h3&gt;
  &lt;p class=&quot;anchored&quot; anchor-name=&quot;--anchor-1&quot; &gt;Content for Anchor 1&lt;/p&gt;  &lt;h3 class=&quot;anchor&quot; anchor-name=&quot;--anchor-2&quot; &gt;Anchor 2&lt;/h3&gt;
  &lt;p class=&quot;anchored&quot; anchor-name=&quot;--anchor-2&quot; &gt;Content for Anchor 2&lt;/p&gt;
&lt;/section&gt;&lt;style&gt;
  .anchor {
    anchor-name: attr(anchor-name type(&lt;custom-ident&gt;));
    margin: 50px;
  }

  .anchored {
    position-anchor: attr(anchor-name type(&lt;custom-ident&gt;));
    position: fixed;
    bottom: anchor(bottom);
    right: anchor(right);
  }
&lt;/style&gt;&lt;p&gt;The above example uses a few interesting bits that I&amp;#39;d like to discuss before throwing a wall of code at you&lt;/p&gt;
&lt;h2&gt;CSS Identifiers&lt;/h2&gt;
&lt;p&gt;Though it does a pretty good job of making everything look like a string - CSS does indeed have data types (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/Data_types&quot; &gt;CSS Data Types - MDN&lt;/a&gt;&lt;/cite&gt;). Usually we don&amp;#39;t need to think too hard about these but they end up being necessary in the above example when using the &lt;code&gt;position-anchor&lt;/code&gt; attribute and &lt;code&gt;attr&lt;/code&gt; function&lt;/p&gt;
&lt;p&gt;An &lt;code&gt;&amp;lt;ident&amp;gt;&lt;/code&gt; is the type used to represent an identifier in CSS (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/ident&quot; &gt;CSS &lt;code&gt;&amp;lt;ident&amp;gt;&lt;/code&gt; - MDN&lt;/a&gt;&lt;/cite&gt;)&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;&amp;lt;custom-ident&amp;gt;&lt;/code&gt; is a case-sensitive string that can be user-defined and used as CSS identifier (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/custom-ident&quot; &gt;CSS &lt;code&gt;&amp;lt;custom-ident&amp;gt;&lt;/code&gt; - MDN&lt;/a&gt;&lt;/cite&gt;)&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;position-anchor&lt;/code&gt; attribute requires a &lt;code&gt;&amp;lt;dashed-ident&amp;gt;&lt;/code&gt; which is a &lt;code&gt;&amp;lt;custom-ident&amp;gt;&lt;/code&gt; that starts with &lt;code&gt;--&lt;/code&gt; (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/dashed-ident&quot; &gt;CSS &lt;code&gt;&amp;lt;dashed-ident&amp;gt;&lt;/code&gt; - MDN&lt;/a&gt;&lt;/cite&gt;). These will never be defined by CSS and are only ever defined by the user&lt;/p&gt;
&lt;p&gt;In our example, we&amp;#39;re receiving our &lt;code&gt;&amp;lt;dashed-ident&amp;gt;&lt;/code&gt; via &lt;code&gt;attr()&lt;/code&gt;. Since a &lt;code&gt;&amp;lt;dashed-ident&amp;gt;&lt;/code&gt; cannot be defined by CSS, the type we will receive from &lt;code&gt;attr()&lt;/code&gt; is a &lt;code&gt;&amp;lt;custom-ident&amp;gt;&lt;/code&gt;. Note that this &lt;strong&gt;must&lt;/strong&gt; start with &lt;code&gt;--&lt;/code&gt; in order to work in the place of a &lt;code&gt;&amp;lt;dashed-ident&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Reading Attributes in CSS&lt;/h2&gt;
&lt;p&gt;The CSS &lt;code&gt;attr()&lt;/code&gt; function lets us read the value of an element attribute and use it in CSS (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/attr&quot; &gt;CSS &lt;code&gt;attr()&lt;/code&gt; - MDN&lt;/a&gt;&lt;/cite&gt;). This means that we can effectively provide variables for use within CSS by way of HTML attributes. This is really handy and has tons of use cases&lt;/p&gt;
&lt;p&gt;In the example above, we&amp;#39;re using the &lt;code&gt;attr()&lt;/code&gt; to read the value of the &lt;code&gt;anchor&lt;/code&gt; attribute. Some ways of using &lt;code&gt;attr()&lt;/code&gt; can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/* basic */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;attr(&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;attribute-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/* with a unit or type*/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;attr(&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;attribute-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; unit)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;attr(&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;attribute-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; type(&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;css-type&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;To actually use this, we can specify an attribute on an HTML element like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchor&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Anchor 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And we can then read an attribute, for example - the &lt;code&gt;anchor-name&lt;/code&gt; attribute as a &lt;code&gt;&amp;lt;custom-ident&amp;gt;&lt;/code&gt;, using &lt;code&gt;attr()&lt;/code&gt; as seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.anchor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;attr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;anchor-name&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; type(&amp;lt;custom-ident&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;attr()&lt;/code&gt; can be used to read data from an attribute and use it in CSS pretty much anywhere that we&amp;#39;d normally use hard-coded data&lt;/p&gt;
&lt;h2&gt;Anchor Positioning&lt;/h2&gt;
&lt;p&gt;Now that we&amp;#39;ve covered what the &lt;code&gt;attr&lt;/code&gt; and &lt;code&gt;&amp;lt;custom-ident&amp;gt;&lt;/code&gt; syntax is all about, we can dive into anchor positioning&lt;/p&gt;
&lt;p&gt;Anchor positioning is a set of CSS attributes and behaviors that make it possible to connect the positions and sizes of different elements (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Anchor_positioning&quot; &gt;CSS anchor positioning - MDN&lt;/a&gt;&lt;/cite&gt;). For the sake of this example, we&amp;#39;ll use the different parts of the anchor positioning module to place an element at the top-right of another element. Making this work requires us to define the anchor element. This is done using the &lt;code&gt;anchor-name&lt;/code&gt; property on said element (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/anchor-name&quot; &gt;CSS anchor-name - MDN&lt;/a&gt;&lt;/cite&gt;):&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchor-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Anchor 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.anchor-1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: --anchor-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then, we can reference this &lt;code&gt;anchor-name&lt;/code&gt; from any elements that want to position themselves relative to this with the &lt;code&gt;position-anchor&lt;/code&gt; property which specifies the name of the anchor element (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/position-anchor&quot; &gt;CSS position-anchor - MDN&lt;/a&gt;&lt;/cite&gt;)&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchored-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Content for Anchor 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.anchored-1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  position-anchor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: --anchor-1;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;fixed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: anchor(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: anchor(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;In the above, we specify &lt;code&gt;position: fixed&lt;/code&gt; to place this element relative to the &lt;code&gt;position-anchor&lt;/code&gt; and out of the normal document flow (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/position&quot; &gt;CSS position - MDN&lt;/a&gt;&lt;/cite&gt;)&lt;/p&gt;
&lt;p&gt;The CSS &lt;code&gt;anchor()&lt;/code&gt; function is used to return the length relative to the anchor element and allows us to position the anchored element relative to the anchor (&lt;cite&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/anchor&quot; &gt;CSS &lt;code&gt;anchor()&lt;/code&gt; - MDN&lt;/a&gt;&lt;/cite&gt;)&lt;/p&gt;
&lt;h2&gt;Putting It Together&lt;/h2&gt;
&lt;p&gt;The example above is fairly repetitive. For each element having to redefine a CSS rule sets the &lt;code&gt;anchor-name&lt;/code&gt; and &lt;code&gt;position-anchor&lt;/code&gt; can become tedious. There are two solutions that will give us some kind of reusability here, namely:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using a CSS custom property that is set on the element&lt;/li&gt;
&lt;li&gt;Using a custom HTML attribute and reading that in the CSS&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Lately I&amp;#39;ve been liking the use of custom HTML attributes as a hook for styling - this is inspired by the &lt;a href=&quot;https://jordanbrennan.hashnode.dev/tac-a-new-css-methodology&quot; &gt;TAC CSS Methodology&lt;/a&gt; which uses Tags, Attributes, and Classes - in that order - as styling hooks&lt;/p&gt;
&lt;p&gt;As such, the below example uses the &lt;code&gt;anchor-name&lt;/code&gt; attribute on the HTML element to define the values to use for &lt;code&gt;anchor-name&lt;/code&gt; and &lt;code&gt;position-anchor&lt;/code&gt;, which we then read in the CSS using &lt;code&gt;attr()&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchor&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Anchor 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchored&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Content for Anchor 1&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And then, define generic CSS rules that can work with any provided &lt;code&gt;anchor-name&lt;/code&gt; attribute and read them accordingly:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;css&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.anchor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;attr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;anchor-name&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; type(&amp;lt;custom-ident&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  margin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;50&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;.anchored&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  position-anchor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;attr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;anchor-name&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; type(&amp;lt;custom-ident&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;fixed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: anchor(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: anchor(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Putting that together gets the behavior we&amp;#39;re after in a pretty neat and reusable way&lt;/p&gt;
&lt;h2&gt;The Big Example&lt;/h2&gt;
&lt;p&gt;Putting all the above together, we can get back to the code for the original example, which can be seen once more below:&lt;/p&gt;
&lt;section&gt;
  &lt;h3 class=&quot;anchor&quot; anchor-name=&quot;--anchor-3&quot; &gt;Anchor 3&lt;/h3&gt;
  &lt;p class=&quot;anchored&quot; anchor-name=&quot;--anchor-3&quot; &gt;Content for Anchor 3&lt;/p&gt;  &lt;h3 class=&quot;anchor&quot; anchor-name=&quot;--anchor-4&quot; &gt;Anchor 4&lt;/h3&gt;
  &lt;p class=&quot;anchored&quot; anchor-name=&quot;--anchor-4&quot; &gt;Content for Anchor 4&lt;/p&gt;
&lt;/section&gt;&lt;style&gt;
  .anchor {
    anchor-name: attr(anchor-name type(&lt;custom-ident&gt;));
    margin: 50px;
  }

  .anchored {
    position-anchor: attr(anchor-name type(&lt;custom-ident&gt;));
    position: fixed;
    bottom: anchor(bottom);
    right: anchor(right);
  }
&lt;/style&gt;&lt;p&gt;The respective HTML and CSS is as follows:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchor&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-3&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Anchor 3&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchored&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-3&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Content for Anchor 3&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchor&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-4&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Anchor 4&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h3&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;anchored&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;--anchor-4&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Content for Anchor 4&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .anchor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    anchor-name&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;attr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;anchor-name&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; type(&amp;lt;custom-ident&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    margin&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;50&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;px&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;  .anchored&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    position-anchor&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;attr&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;anchor-name&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; type(&amp;lt;custom-ident&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    position&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;fixed&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: anchor(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;bottom&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;    right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;: anchor(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;right&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2&gt;Accessibility Notes&lt;/h2&gt;
&lt;p&gt;Be careful with this idea, though it&amp;#39;s useful to move elements around the screen arbitrarily but it&amp;#39;s probably undesirable from an accessibility standpoint. Try to ensure that the elements are still related logically and ordered so that screen readers and other accessibility tools work as you&amp;#39;d intend&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;The above APIs can also be a handy addition to the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover&quot; &gt;HTML popover attribute&lt;/a&gt; and can lead to some nice JavaScript-free behaviors&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Quirky Times</title><link>https://nabeelvalley.co.za/blog/2026/11-06/quirky-times.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/11-06/quirky-times.html</guid><description>Some very random pictures that I took recently</description><pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Quirky Times&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I saw a video the other day that said basically just said &amp;quot;horizon in the middle = bad&amp;quot; so I decided to take a bunch of pictures last weekend with the goal being &amp;quot;horizon somewhere else&amp;quot;. Seems like looking anywhere but straight ahead is pretty interesting&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Bags-of-trash.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Bags of trash&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Bags%20of%20trash.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Bicycle-on-hill-parked-agains-pole.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Bicycle on hill parked agains pole&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Bicycle%20on%20hill%20parked%20agains%20pole.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Butterfly-on-flowers.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Butterfly on flowers&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Butterfly%20on%20flowers.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Crate-of-unfried-fries-in-bags.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Crate of unfried fries in bags&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Crate%20of%20unfried%20fries%20in%20bags.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Hiker-walking-up-escalator.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Hiker walking up escalator&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Hiker%20walking%20up%20escalator.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---House-with-scaffolding-outside.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - House with scaffolding outside&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20House%20with%20scaffolding%20outside.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Jeans-hanging-between-the-buildings.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Jeans hanging between the buildings&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Jeans%20hanging%20between%20the%20buildings.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---One-way-sign-pointing-upwards.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - One-way-sign pointing upwards&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20One-way-sign%20pointing%20upwards.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Pands-hanging-between-buildings-with-building-in-back.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Pands hanging between buildings with building in back&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Pands%20hanging%20between%20buildings%20with%20building%20in%20back.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Pink-flowers-on-tree.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Pink flowers on tree&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Pink%20flowers%20on%20tree.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---Top-of-carousel-with-cartoon-characters-on-it.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - Top of carousel with cartoon characters on it&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20Top%20of%20carousel%20with%20cartoon%20characters%20on%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-11---quirky-times/2026-05-31---xt35---color---NL---Utrecht---White-flowers.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-05-31 - xt35 - color - NL - Utrecht - White flowers&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-11%20-%20quirky-times/2026-05-31%20-%20xt35%20-%20color%20-%20NL%20-%20Utrecht%20-%20White%20flowers.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Join the Webring!</title><link>https://nabeelvalley.co.za/blog/2026/12-03/webring.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/12-03/webring.html</guid><description>I&#39;m starting a Webring!</description><pubDate>Thu, 12 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Join the Webring!&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Assumed audience: People with a personal website or anyone interested in the indie web&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#39;ve wanted to start a &lt;a href=&quot;https://en.wikipedia.org/wiki/Webring&quot; &gt;Webring&lt;/a&gt; for a while now and finally got around to it. Click the links in the footer to explore!&lt;/p&gt;
&lt;h2&gt;Would You like to Join?&lt;/h2&gt;
&lt;p&gt;That&amp;#39;s great! You need to do two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add the following HTML to your site&amp;#39;s footer (or some variation of those 4 links) - style it however you like!&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://webring.nabeelvalley.co.za&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;em&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Webring&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;em&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;links&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://webring.nabeelvalley.co.za/previous?referer=your.domain.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Previous&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://webring.nabeelvalley.co.za/random?referer=your.domain.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Random&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; href&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;https://webring.nabeelvalley.co.za/next?referer=your.domain.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Next&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;li&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;ul&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;section&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Make sure to replace the &lt;code&gt;your.domain.com&lt;/code&gt; with your actual domain - as listed in &lt;code&gt;src/config.gleam&lt;/code&gt; of course&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;2&quot; &gt;
&lt;li&gt;Make a pull request adding your site to the &lt;a href=&quot;https://github.com/nabeelvalley/webring&quot; &gt;webring repo&lt;/a&gt; at &lt;a href=&quot;https://github.com/nabeelvalley/webring/blob/main/src/config.gleam&quot; &gt;&lt;code&gt;src/config.gleam&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that should do it! Welcome to the web&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>HTML in WebGPU Shaders in Canvas</title><link>https://nabeelvalley.co.za/blog/2026/12-04/html-in-canvas.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/12-04/html-in-canvas.html</guid><description>A little experimet with Web GPU Shaders with HTML</description><pubDate>Sun, 12 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;HTML in WebGPU Shaders in Canvas&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I made some minor updates to my &lt;a href=&quot;/blog/2025/09-11/shader-web-component&quot; &gt;Shader Web Component&lt;/a&gt; to add support for the &lt;a href=&quot;https://github.com/WICG/html-in-canvas&quot; &gt;proposed HTML-in-Canvas API&lt;/a&gt;. So you can see the following in a Chromium based browser with the flag &lt;code&gt;chrome://flags/#canvas-draw-element&lt;/code&gt; enabled&lt;/p&gt;
&lt;site-shader-canvas&gt;
  &lt;canvas width=&quot;1000&quot; height=&quot;1000&quot; style=&quot;width: 100%&quot; layoutsubtree=&quot;&quot; &gt;
    &lt;div class=&quot;html-in-canvas&quot; style=&quot;width: 100%; height: 100%; color: green; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;&quot; &gt;
      &lt;h2 style=&quot;margin: 0;&quot; &gt;Hello from HTML!&lt;/h2&gt;      &lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;lt;label for=&amp;quot;input-in-canvas&amp;quot;&amp;gt;Input in canvas&amp;lt;/label&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;  &amp;lt;input style=&amp;quot;display: block;&amp;quot; id=&amp;quot;input-in-canvas&amp;quot; /&amp;gt;      &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
  &lt;/div&gt;&lt;/canvas&gt;  &lt;script type=&quot;text/wgsl&quot; &gt;
    struct VertexOutput {
      @builtin(position) position: vec4f,
      @location(0) texcoord: vec2f,
    };

    @vertex fn vs(
      @builtin(vertex_index) vertexIndex : u32
    ) -&gt; VertexOutput {
      const pos = array(
        vec2( 1.0,  1.0),
        vec2( 1.0, -1.0),
        vec2(-1.0, -1.0),
        vec2( 1.0,  1.0),
        vec2(-1.0, -1.0),
        vec2(-1.0,  1.0),
      );

      var vsOutput: VertexOutput;
  
      let xy = pos[vertexIndex];
      vsOutput.texcoord = pos[vertexIndex] * vec2f(0.5, 0.5) + vec2f(0.5);
      vsOutput.position = vec4f(pos[vertexIndex], 0, 1);

      return vsOutput;
    }

    @group(0) @binding(0) var htmlSampler: sampler;
    @group(0) @binding(1) var htmlTexture: texture_2d&lt;f32&gt;;

    @group(1) @binding(0) var&lt;uniform&gt; uTime: f32;

    fn flipSample(fsInput: VertexOutput) -&gt; vec4f {
      // the texture must be flipped since the shader coord system is the
      // opposite of the HTML one
      var pos = vec2f(fsInput.texcoord.x, 1 - fsInput.texcoord.y);
      return textureSample(htmlTexture, htmlSampler, pos);
    }
    
    @fragment fn fs(fsInput: VertexOutput) -&gt; @location(0) vec4f {
      var red = abs(sin(uTime/10.0)) * fsInput.texcoord.x;
      var blue = abs(cos(uTime/5.0)) * fsInput.texcoord.y;

      return vec4f(red, 0.0, blue, 1.0) + flipSample(fsInput);
    }
  &lt;/script&gt;
&lt;/site-shader-canvas&gt;&lt;h2&gt;How Does It Work?&lt;/h2&gt;
&lt;p&gt;The HTML in the above example is rendered within the canvas and is - if/when supported - exposed to the accessibility tree&lt;/p&gt;
&lt;p&gt;As per the documentation, this makes use of the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;layoutsubtree&lt;/code&gt; attribute on the &lt;code&gt;canvas&lt;/code&gt; element to tell the browser that we want to render the contents&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;copyElementImageToTexture&lt;/code&gt; function on the WebGPU &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/queue&quot; &gt;&lt;code&gt;GPUDevice.queue&lt;/code&gt;&lt;/a&gt; to copy the texture&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;canvas.onpaint&lt;/code&gt; handler to run the &lt;code&gt;copyElementImageToTexture&lt;/code&gt; function with the contents&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Usability Issues&lt;/h2&gt;
&lt;p&gt;The proposal is still just that - a proposal - so it has some issues and is still very experimental.&lt;/p&gt;
&lt;p&gt;The above example should show the inner content if supported. I&amp;#39;ve noticed that there are some quirks around how the content focus, etc. work since the click targets aren&amp;#39;t aligned as expected, etc. which creates some weird usability issues&lt;/p&gt;
&lt;p&gt;Some challenges I see here are around keeping positions in sync so that interactive elements remain correctly interactive and that basic parts of the web continue to work as users expect&lt;/p&gt;
&lt;p&gt;The example above originally suffered from the fact that the size of the canvas content doesn&amp;#39;t match the canvas and so things are not quite in the right place. &lt;a href=&quot;https://mattrothenberg.com/&quot; &gt;Matt Rothenberg&lt;/a&gt; also points this out in their &lt;a href=&quot;https://mattrothenberg.com/notes/html-in-canvas/&quot; &gt;HTML in Canvas&lt;/a&gt; post and while it&amp;#39;s definitely doable it does require a fair amount of wrangling to make work nicely&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve solved the resizing issue in the above example using CSS but it&amp;#39;s also possible to do using the &lt;code&gt;drawElementImage&lt;/code&gt; function as per the API to do the necessary alignment&lt;/p&gt;
&lt;h2&gt;Technical Challenges&lt;/h2&gt;
&lt;p&gt;I also ran into some VERY annoying bugs (or is this just how WebGPU is meant to work - I don&amp;#39;t know) along the way, the main one was to do with figuring out how to use the GPU bindings&lt;/p&gt;
&lt;p&gt;In particular, I saw the following error about a million times:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;text&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span&gt;In entries[0], binding index 0 not present in the bind group layout.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;Expected layout: []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt; - While validating [BindGroupDescriptor &amp;quot;&amp;quot;textures&amp;quot;&amp;quot;] against [BindGroupLayout (unlabeled)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt; - While calling [Device].CreateBindGroup([BindGroupDescriptor &amp;quot;&amp;quot;textures&amp;quot;&amp;quot;]).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This was because the bindings in my shader related to the textures were not used:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;wgsl&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// unused&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;binding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; htmlSampler: sampler;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;binding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; htmlTexture: texture_2d&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;f32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// used&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;@&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;binding&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;uniform&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt; uTime: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;f32&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The respective texture and sampler were not used, and so the &lt;code&gt;auto&lt;/code&gt; layout for the shader doesn&amp;#39;t seem to detect that they exist. I find this very confusing - the error here could be better&lt;/p&gt;
&lt;p&gt;There&amp;#39;s a good example on explicitly defining the layouts on &lt;a href=&quot;https://webgpufundamentals.org/webgpu/lessons/webgpu-bind-group-layouts.html&quot; &gt;this WebGPU Bind Group Layouts article&lt;/a&gt; and &lt;a href=&quot;https://webgpufundamentals.org/webgpu/lessons/resources/wgsl-offset-computer.html&quot; &gt;a handy calculator for providing the bind group layout config&lt;/a&gt;. This ended up eventually being how I realized the bind group was being left out since for some reason the entries in &lt;code&gt;@group(0)&lt;/code&gt; were being left out even though their example - when updated to use &amp;quot;my&amp;quot; bindings for the texture and sampler - worked just fine.&lt;/p&gt;
&lt;p&gt;Anyways, ensuring that the sampler and texture are used meant that everything worked fine again. So conditionally adding the bindgroup works which adds some ugliness to my shader rendering code but I think it&amp;#39;s fine for what it makes possible&lt;/p&gt;
&lt;p&gt;The snippet for the above example can be seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;html&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;site-shader-canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;canvas&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; width&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;1000&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; height&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;1000&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;width: 100%&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; layoutsubtree&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; class&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;html-in-canvas&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;width: 100%; height: 100%; color: green; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h2&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;margin: 0;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Hello from HTML!&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;h2&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;      &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;label&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;input-in-canvas&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;Input in canvas&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;label&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;input&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; style&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;display: block;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; id&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;input-in-canvas&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; /&amp;gt;      &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;div&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;text/wgsl&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    struct VertexOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      @builtin(position) position: vec4f,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      @location(0) texcoord: vec2f,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @vertex fn vs(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      @builtin(vertex_index) vertexIndex : u32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    ) -&amp;gt; VertexOutput {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      const pos = array(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2( 1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2( 1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2(-1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2( 1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2(-1.0, -1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;        vec2(-1.0,  1.0),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var vsOutput: VertexOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      let xy = pos[vertexIndex];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      vsOutput.texcoord = pos[vertexIndex] * vec2f(0.5, 0.5) + vec2f(0.5);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      vsOutput.position = vec4f(pos[vertexIndex], 0, 1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      return vsOutput;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @group(0) @binding(0) var htmlSampler: sampler;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @group(0) @binding(1) var htmlTexture: texture_2d&amp;lt;f32&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @group(1) @binding(0) var&amp;lt;uniform&amp;gt; uTime: f32;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    fn flipSample(fsInput: VertexOutput) -&amp;gt; vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      // the texture must be flipped since the shader coord system is the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      // opposite of the HTML one&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var pos = vec2f(fsInput.texcoord.x, 1 - fsInput.texcoord.y);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      return textureSample(htmlTexture, htmlSampler, pos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    @fragment fn fs(fsInput: VertexOutput) -&amp;gt; @location(0) vec4f {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var red = abs(sin(uTime/10.0)) * fsInput.texcoord.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      var blue = abs(cos(uTime/5.0)) * fsInput.texcoord.y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;      return vec4f(red, 0.0, blue, 1.0) + flipSample(fsInput);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;script&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#024C1A;--shiki-dark:#72F088&quot; &gt;site-shader-canvas&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;You can also take a look at the &lt;a href=&quot;/web-components/shader-canvas.js&quot; &gt;source of the web component&lt;/a&gt; and respective &lt;a href=&quot;/web-components/shader.js&quot; &gt;shader renderer&lt;/a&gt; if you&amp;#39;re interested&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Cash4Tricks</title><link>https://nabeelvalley.co.za/blog/2026/13-06/cash-4-tricks.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/13-06/cash-4-tricks.html</guid><description>Photos from a small skate competition in Utrecht</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Cash4Tricks&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Stopped by &lt;a href=&quot;https://skateparkutrecht.nl/&quot; &gt;Skatepark Utrecht&lt;/a&gt; for the skate event which ended up being a really good vibe. It ran till pretty late but I stayed for the competition part at least. Didn&amp;#39;t get the hear the band shred it or stay for the film screening but it was 10pm and I was tiiired&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Double-heelflip-from-leap-of-faith.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Double heelflip from leap of faith&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Double%20heelflip%20from%20leap%20of%20faith.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Flip-trick-from-leap-of-faith.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Flip trick from leap of faith&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Flip%20trick%20from%20leap%20of%20faith.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Flip-trick-over-picnic-table.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Flip trick over picnic table&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Flip%20trick%20over%20picnic%20table.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Flip-trick-over-table.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6664445184938353&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Flip trick over table&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Flip%20trick%20over%20table.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Flip-trick.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Flip trick&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Flip%20trick.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Grab-from-leap-of-faith.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Grab from leap of faith&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Grab%20from%20leap%20of%20faith.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Grind-on-coping.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Grind on coping&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Grind%20on%20coping.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Grind.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Grind&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Grind.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Jumping-over-picnic-table-2.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Jumping over picnic table 2&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Jumping%20over%20picnic%20table%202.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Jumping-over-picnic-table-3.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Jumping over picnic table 3&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Jumping%20over%20picnic%20table%203.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Jumping-over-picnic-table.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Jumping over picnic table&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Jumping%20over%20picnic%20table.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Jumping-over-rail.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Jumping over rail&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Jumping%20over%20rail.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Leap-of-faith.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Leap of faith&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Leap%20of%20faith.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---No-comply-on-picnic-table.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - No-comply on picnic table&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20No-comply%20on%20picnic%20table.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-13---cash-4-tricks/2026-06-13---xt35---bw---NL---Utrecht---Trick-over-table.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-13 - xt35 - bw - NL - Utrecht - Trick over table&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-13%20-%20cash-4-tricks/2026-06-13%20-%20xt35%20-%20bw%20-%20NL%20-%20Utrecht%20-%20Trick%20over%20table.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Blow-up Jubilee - Den Haag</title><link>https://nabeelvalley.co.za/blog/2026/14-06/blow-up-jubilee-den-haag.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/14-06/blow-up-jubilee-den-haag.html</guid><description>The Blow-up art exhibit in Den Haag</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Blow-up Jubilee - Den Haag&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;Took a walk around the city trying to spot the exhibits. I didn&amp;#39;t want to take my camera off black and white mode though so here you go with a gloomy interpretation of the wacky exhibit&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Crested-by-Steve-Messam-(2).html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Crested by Steve Messam (2)&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Crested%20by%20Steve%20Messam%20(2).webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---De-Juiste-Richting-by-Kiki-&amp;amp;-Joost.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - De Juiste Richting by Kiki &amp;amp; Joost&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20De%20Juiste%20Richting%20by%20Kiki%20%26%20Joost.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---De-juiste-richting-by-Kiki-&amp;amp;-Joost-(2).html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - De juiste richting by Kiki &amp;amp; Joost (2)&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20De%20juiste%20richting%20by%20Kiki%20%26%20Joost%20(2).webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Een-groot-hart---Yamuna-Forzani.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Een groot hart - Yamuna Forzani&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Een%20groot%20hart%20-%20Yamuna%20Forzani.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Eiren-by-Marcel-Wanders-(2).html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Eiren by Marcel Wanders (2)&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Eiren%20by%20Marcel%20Wanders%20(2).webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Eiren-by-Marcel-Wanders-(3).html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Eiren by Marcel Wanders (3)&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Eiren%20by%20Marcel%20Wanders%20(3).webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Eiren-by-Marcel-Wanders.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Eiren by Marcel Wanders&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Eiren%20by%20Marcel%20Wanders.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Gazebo-by-Sigrid-Calon.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Gazebo by Sigrid Calon&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Gazebo%20by%20Sigrid%20Calon.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Keep-me-in-balance-by-Larissa-Ambachtsheer.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Keep me in balance by Larissa Ambachtsheer&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Keep%20me%20in%20balance%20by%20Larissa%20Ambachtsheer.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Krested-by-Steve-Messam.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Krested by Steve Messam&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Krested%20by%20Steve%20Messam.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Oranje-by-Steve-Messam-(2).html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Oranje by Steve Messam (2)&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Oranje%20by%20Steve%20Messam%20(2).webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Oranje-by-Steve-Messam.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Oranje by Steve Messam&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Oranje%20by%20Steve%20Messam.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-06-14---blow-up-jubilee/2026-06-14---xt35---bw---NL---Den-Haag---Blow-up-Jubilee---Tunnel-by-Steve-Messam.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-06-14 - xt35 - bw - NL - Den Haag - Blow-up Jubilee - Tunnel by Steve Messam&quot; src=&quot;/optimized-images/content/photography/blog/2026-06-14%20-%20blow-up%20jubilee/2026-06-14%20-%20xt35%20-%20bw%20-%20NL%20-%20Den%20Haag%20-%20Blow-up%20Jubilee%20-%20Tunnel%20by%20Steve%20Messam.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;p&gt;Thanks also to these pages that helped me get the names of the exhibits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://djaktief.wordpress.com/2026/05/24/den-haag-blowup-art/&quot; &gt;Den Haag BlowUp art - djaktief&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://djaktief.wordpress.com/2026/05/25/den-haag-blowup-art-vervolg/&quot; &gt;Den Haag BlowUp art vervolg - djaktief&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://denhaag.com/nl/blowup&quot; &gt;BlowUp Jubilee! | DenHaag.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Web Component for Making Patterns</title><link>https://nabeelvalley.co.za/blog/2026/17-02/pattern-web-component.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/17-02/pattern-web-component.html</guid><description>A web component for defining geometric patterns</description><pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Web Component for Making Patterns&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I made a small web component for defining geometric patterns, you can see the component in action here:&lt;/p&gt;
&lt;p&gt;(inspect the JS if you&amp;#39;d like to see what&amp;#39;s happening, though it&amp;#39;s just some bad SVG stuff)&lt;/p&gt;
&lt;script src=&quot;/web-components/pattern.js&quot; &gt;&lt;/script&gt;&lt;site-pattern scale=&quot;20&quot; pattern-x=&quot;0 1 0 0 1 0 1 1&quot; pattern-y=&quot;1 0 0&quot; &gt;
  &lt;svg style=&quot;width: 100%; aspect-ratio: 3/2&quot; &gt;&lt;/svg&gt;
&lt;/site-pattern&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>People used to live here</title><link>https://nabeelvalley.co.za/blog/2026/18-07/people-used-to-live-here.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/18-07/people-used-to-live-here.html</guid><description>Abandoned photos of the beach in Scheveningen</description><pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;People used to live here&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I went to the beach today and noticed a bunch of weird stuff. I made a small collection of photos with the idea of &amp;quot;a world after humanity&amp;quot;. Thinking about the unnaturalness of our own existence and how that shapes the world around us&lt;/p&gt;
&lt;h2&gt;The Photos&lt;/h2&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Abandoned-booth-of-some-kind.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Abandoned booth of some kind&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Abandoned%20booth%20of%20some%20kind.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Abandoned-building.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Abandoned building&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Abandoned%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Abandoned-park-on-beach-with-weird-sculptures-around-it.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Abandoned park on beach with weird sculptures around it&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Abandoned%20park%20on%20beach%20with%20weird%20sculptures%20around%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Art-with-bottle-caps.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Art with bottle caps&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Art%20with%20bottle%20caps.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Bench-next-to-beach.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Bench next to beach&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Bench%20next%20to%20beach.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Bike-parked-next-to-fence-with-church-in-background.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Bike parked next to fence with church in background&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Bike%20parked%20next%20to%20fence%20with%20church%20in%20background.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Bike-parked-next-to-fence.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Bike parked next to fence&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Bike%20parked%20next%20to%20fence.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Bin-with-grafitti-and-3-fish-with-crowns.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Bin with grafitti and 3 fish with crowns&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Bin%20with%20grafitti%20and%203%20fish%20with%20crowns.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Concrete-blocks-along-path.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Concrete blocks along path&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Concrete%20blocks%20along%20path.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Concrete-on-side-of-pier.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Concrete on side of pier&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Concrete%20on%20side%20of%20pier.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Creepy-chair.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Creepy chair&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Creepy%20chair.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Creepy-manequins-on-top-of-building-with-ferris-wheel-in-background.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Creepy manequins on top of building with ferris wheel in background&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Creepy%20manequins%20on%20top%20of%20building%20with%20ferris%20wheel%20in%20background.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Door-surrounded-by-paintings-of-fish.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Door surrounded by paintings of fish&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Door%20surrounded%20by%20paintings%20of%20fish.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Lamp-post-with-the-number-4.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Lamp post with the number 4&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Lamp%20post%20with%20the%20number%204.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Light-poles-on-the-beach.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Light poles on the beach&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Light%20poles%20on%20the%20beach.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Light-post-with-shoe-stuck-on-it.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Light post with shoe stuck on it&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Light%20post%20with%20shoe%20stuck%20on%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Light-posts-along-beachside.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Light posts along beachside&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Light%20posts%20along%20beachside.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Lighthouse.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Lighthouse&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Lighthouse.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Old-vending-maching-for-toys.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Old vending maching for toys&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Old%20vending%20maching%20for%20toys.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Parking-sign-with-lighthouse-in-the-background.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Parking sign with lighthouse in the background&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Parking%20sign%20with%20lighthouse%20in%20the%20background.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Plant-between-low-walls.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Plant between low walls&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Plant%20between%20low%20walls.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Plant-growing-on-side-of-staircase.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Plant growing on side of staircase&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Plant%20growing%20on%20side%20of%20staircase.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Plants-with-dandelion-esque-seeds.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Plants with dandelion-esque seeds&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Plants%20with%20dandelion-esque%20seeds.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Sculpture-of-person-made-out-of-scrap-material.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sculpture of person made out of scrap material&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sculpture%20of%20person%20made%20out%20of%20scrap%20material.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Sign-saying-Museum-van-Gevonden-Schatten.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sign saying Museum van Gevonden Schatten&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sign%20saying%20Museum%20van%20Gevonden%20Schatten.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Sign-that-says-Voor-Naam-Gegrift-In-Steen.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sign that says Voor Naam Gegrift In Steen&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sign%20that%20says%20Voor%20Naam%20Gegrift%20In%20Steen.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Signs-pointing-to-different-places-on-the-beach.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Signs pointing to different places on the beach&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Signs%20pointing%20to%20different%20places%20on%20the%20beach.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Slide-with-creepy-mannequin-on-top.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Slide with creepy mannequin on top&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Slide%20with%20creepy%20mannequin%20on%20top.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Statue-in-the-middle-of-an-empty-area.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Statue in the middle of an empty area&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Statue%20in%20the%20middle%20of%20an%20empty%20area.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Sticker-on-post-that-says-Kids-of-Tomorrow.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sticker on post that says Kids of Tomorrow&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sticker%20on%20post%20that%20says%20Kids%20of%20Tomorrow.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Store-with-mannequins-on-top-of-it.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Store with mannequins on top of it&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Store%20with%20mannequins%20on%20top%20of%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Three-fish-with-crowns-engraved-into-stone.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Three fish with crowns engraved into stone&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Three%20fish%20with%20crowns%20engraved%20into%20stone.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Three-fish-with-crowns-next-to-a-dutch-flag-on-the-side-of-a-bin.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Three fish with crowns next to a dutch flag on the side of a bin&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Three%20fish%20with%20crowns%20next%20to%20a%20dutch%20flag%20on%20the%20side%20of%20a%20bin.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Top-half-of-mannequin-beside-giant-ice-cream-cone.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Top half of mannequin beside giant ice cream cone&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Top%20half%20of%20mannequin%20beside%20giant%20ice%20cream%20cone.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Wall-of-names.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Wall of names&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Wall%20of%20names.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---people-used-to-live-here/2026-07-18---xt15-45---bw---NL---Scheveningen---Weird-arrangement-of-concrete-chairs.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Weird arrangement of concrete chairs&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20people%20used%20to%20live%20here/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Weird%20arrangement%20of%20concrete%20chairs.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;h2&gt;Just the Beach&lt;/h2&gt;
&lt;p&gt;I also took some other pictures because there was a bunch of interesting stuff around&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---People-on-zipline-with-ferris-wheel-and-see-in-background.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - People on zipline with ferris wheel and see in background&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20People%20on%20zipline%20with%20ferris%20wheel%20and%20see%20in%20background.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Person-mounting-sculpture-of-head.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Person mounting sculpture of head&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Person%20mounting%20sculpture%20of%20head.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Person-on-zipline.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Person on zipline&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Person%20on%20zipline.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Sculpture-of-being-eating-a-fish.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sculpture of being eating a fish&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sculpture%20of%20being%20eating%20a%20fish.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Sculpture-of-being-with-noose-around-its-neck.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sculpture of being with noose around its neck&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sculpture%20of%20being%20with%20noose%20around%20its%20neck.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Sculpture-of-crying-being.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Sculpture of crying being&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Sculpture%20of%20crying%20being.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Seagulls.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Seagulls&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Seagulls.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-07-18---the-beach/2026-07-18---xt15-45---bw---NL---Scheveningen---Tree-with-ferris-wheel-in-background.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-07-18 - xt15-45 - bw - NL - Scheveningen - Tree with ferris wheel in background&quot; src=&quot;/optimized-images/content/photography/blog/2026-07-18%20-%20the%20beach/2026-07-18%20-%20xt15-45%20-%20bw%20-%20NL%20-%20Scheveningen%20-%20Tree%20with%20ferris%20wheel%20in%20background.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;h2&gt;Closing Remarks&lt;/h2&gt;
&lt;p&gt;Oh and I got attacked by seagulls and they took every bite of my kibbeling. Was weird.&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Mildly interesting photos from Eid</title><link>https://nabeelvalley.co.za/blog/2026/22-03/mildly-interesting-eid.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/22-03/mildly-interesting-eid.html</guid><pubDate>Sun, 22 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Mildly interesting photos from Eid&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;It was Eid on Friday (20 March). We spent it with some friends which is so different to when living near family. It&amp;#39;s quieter and far less chaotic. The Cherry Blossoms are in bloom and the sun was out though - so I took some pictures&lt;/p&gt;
&lt;p&gt;Also a few fairly random things happened so I figured I&amp;#39;d list them for amusement&amp;#39;s sake&lt;/p&gt;
&lt;p&gt;When we went to the Masjid for the &lt;a href=&quot;https://en.wikipedia.org/wiki/Eid_prayers&quot; &gt;Eid Salaah&lt;/a&gt; Shaheed thought that the drink being served was &lt;a href=&quot;https://en.wikipedia.org/wiki/Boeber&quot; &gt;Boeber&lt;/a&gt; (which of course, it wasn&amp;#39;t - because why would it be at a Moroccan Masjid in the Netherlands?). Anyways - it was fun watching him realize it was in fact just a cup of milk.&lt;/p&gt;
&lt;p&gt;In the afternoon, on the way to &lt;a href=&quot;https://en.wikipedia.org/wiki/Friday_prayer&quot; &gt;Jummah&lt;/a&gt; I saw a giant hole being dug next to the shopping center so I made a mental note to take a picture of it on my way home&lt;/p&gt;
&lt;p&gt;On the way to the Masjid still, my path was blocked by a school of kids cycling with bright orange vests and teachers shouting &amp;quot;Trappen voor je leven!&amp;quot;. There were like a lot of them&lt;/p&gt;
&lt;p&gt;Then on the way back from the Masjid, after taking my picture of the giant hole - I stopped and took a few of the cherry blossoms. The old man sitting outside his apartment building in the sun shouted at me to get some from the other side where the sun was coming from to which I obliged&lt;/p&gt;
&lt;p&gt;Anyways, all that to say - here are some random pictures from the past week&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2023-03-15---xt35---color---NL---Blue-ripstick-board-laying-on-the-side-of-the-path.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2023-03-15 - xt35 - color - NL - Blue ripstick board laying on the side of the path&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2023-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Blue%20ripstick%20board%20laying%20on%20the%20side%20of%20the%20path.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-08---xt35---color---NL---Number-67-in-blue-chalk-on-the-sidewalk.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-08 - xt35 - color - NL - Number 67 in blue chalk on the sidewalk&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-08%20-%20xt35%20-%20color%20-%20NL%20-%20Number%2067%20in%20blue%20chalk%20on%20the%20sidewalk.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Book-on-bench-in-the-sun.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Book on bench in the sun&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Book%20on%20bench%20in%20the%20sun.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Bushes-of-yellow-flowers-in-front-of-red-brick-house.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Bushes of yellow flowers in front of red brick house&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Bushes%20of%20yellow%20flowers%20in%20front%20of%20red%20brick%20house.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Little-toy-truck-on-brick-wall.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Little toy truck on brick wall&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Little%20toy%20truck%20on%20brick%20wall.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---NS-train-check-in-machine-with-Capri-Sun-on-floor-next-to-it.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-15 - xt35 - color - NL - NS train check-in machine with Capri Sun on floor next to it&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20NS%20train%20check-in%20machine%20with%20Capri%20Sun%20on%20floor%20next%20to%20it.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Overgrown-bushes.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Overgrown bushes&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Overgrown%20bushes.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Small-yellow-flowers.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Small yellow flowers&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Small%20yellow%20flowers.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Yellow-flowers.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Yellow flowers&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Yellow%20flowers.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-15---xt35---color---NL---Yelow-flower-sticking-through-fence.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6665&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-15 - xt35 - color - NL - Yelow flower sticking through fence&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-15%20-%20xt35%20-%20color%20-%20NL%20-%20Yelow%20flower%20sticking%20through%20fence.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-20---i16---color---NL---Big-hole-being-dug-by-excavator-between-appartment-buildings.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-20 - i16 - color - NL - Big hole being dug by excavator between appartment buildings&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-20%20-%20i16%20-%20color%20-%20NL%20-%20Big%20hole%20being%20dug%20by%20excavator%20between%20appartment%20buildings.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-20---i16---color---NL---Bike-path-with-kids-with-orange-jackets-on.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-20 - i16 - color - NL - Bike path with kids with orange jackets on&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-20%20-%20i16%20-%20color%20-%20NL%20-%20Bike%20path%20with%20kids%20with%20orange%20jackets%20on.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-20---i16---color---NL---Cherry-blossom-tree.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-20 - i16 - color - NL - Cherry blossom tree&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-20%20-%20i16%20-%20color%20-%20NL%20-%20Cherry%20blossom%20tree.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-20---i16---color---NL---Closeup-of-cherry-blossoms.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-20 - i16 - color - NL - Closeup of cherry blossoms&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-20%20-%20i16%20-%20color%20-%20NL%20-%20Closeup%20of%20cherry%20blossoms.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-20---i16---color---NL---Lots-of-cherry-blossom-flowers-on-tree.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-20 - i16 - color - NL - Lots of cherry blossom flowers on tree&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-20%20-%20i16%20-%20color%20-%20NL%20-%20Lots%20of%20cherry%20blossom%20flowers%20on%20tree.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-22---eid/2026-03-20---i16---color---NL---Spiral-staircase-on-side-of-appartment-building.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-20 - i16 - color - NL - Spiral staircase on side of appartment building&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-22%20-%20eid/2026-03-20%20-%20i16%20-%20color%20-%20NL%20-%20Spiral%20staircase%20on%20side%20of%20appartment%20building.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;blockquote&gt;
&lt;p&gt;Update 27 March - I was cycling back from the masjid today and saw an old man stop to take a picture of the big hole. &amp;#39;tis truly universal innit&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Parz v1 finally published!</title><link>https://nabeelvalley.co.za/blog/2026/25-06/parz-v1.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/25-06/parz-v1.html</guid><description>Publishing my parser combinator library</description><pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Parz v1 finally published!&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I&amp;#39;ve been writing a LOT of &lt;a href=&quot;https://gleam.run/&quot; &gt;Gleam&lt;/a&gt; recently. So it felt like it was probably time for me to get my &lt;a href=&quot;/blog/2024/20-07/parser-combinators-and-gleam&quot; &gt;parser combinator library&lt;/a&gt; (aka. &lt;a href=&quot;https://parz.hexdocs.pm/index.html&quot; &gt;&lt;code&gt;parz&lt;/code&gt;&lt;/a&gt;) into a fully usable state&lt;/p&gt;
&lt;p&gt;Since I wrote it back in 2024 (wow that long ago huh?) I hadn&amp;#39;t really had a need for it. Recently I wanted to write some small parsers to help me with my site but the library was still missing one thing that would make it actually sorta useful - recursive parsing&lt;/p&gt;
&lt;p&gt;The actual implementation isn&amp;#39;t really difficult, it&amp;#39;s basically just defining a combinator that delays actually calling a parser which then lets a parser reference itself, for example:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/// Takes a thunk that will be lazily evaluated to a parser. This makes it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;/// possible to define recursive parsers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; lazy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  thunk: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Result&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;ParserState&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(a), &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(state) { &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;thunk&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()(state) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// using it then looks something like this&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  lazy&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    between&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;choice&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;([&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;constant&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()]), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;)&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;    //                                    ^ we can reference ourself in here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Group&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;However, doing this meant that all parsers would have to be made top-level functions since Gleam doesn&amp;#39;t allow for recursion internally&lt;/p&gt;
&lt;p&gt;I tried a few variations of the API that would have let me do something like this but they all ended up depending on some weird fallback behavior. Even then - you&amp;#39;d still have to resort to globals eventually if you depend on any function other than the one being defined - again, due to how local values and functions work in gleam&lt;/p&gt;
&lt;p&gt;This isn&amp;#39;t bad, per se, just not what I had in mind when I designed the API initially&lt;/p&gt;
&lt;p&gt;But I&amp;#39;m fine with it now, it&amp;#39;s only a little different to my ideal version but works well within the constraints of the language and I think parsers are pretty neat with it&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a full example of a parser for parsing simple paths using &lt;code&gt;parz&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;gleam&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parz.{run}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parz&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;combinators.{map, separator}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; parz&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;/&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;parsers.{regex, str}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; Path&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  Path&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;List&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// parsers are defined at the top level to ensure recursion is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// possible if needed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; segment&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // a parser can be made with a pre-defined base parser from `parz/parsers`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  regex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\\&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;w+&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// a more complex parser can be defined by combining other parsers from `parz/combinators`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;  separator&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;segment&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(), &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;str&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Path&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; fn&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; main&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  let&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; result &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;my/example/path&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;parser&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // do something with the parsed output&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;I think that&amp;#39;s not too shabby&lt;/p&gt;
&lt;p&gt;As it stands right now, I&amp;#39;d like to add some more combinators and possibly faster non-regex based string parsers - but since this is mostly just a learning project I&amp;#39;m actually pretty happy it&amp;#39;s reached this level of usability. I&amp;#39;ve even managed to implement a pseudo JSON parser using which is good enough for anything I&amp;#39;m likely to actually use it for&lt;/p&gt;
&lt;p&gt;In conclusion, my little library has been promoted to v1, &lt;a href=&quot;https://parz.hexdocs.pm/index.html&quot; &gt;go and check it out!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And if you haven&amp;#39;t already - definitely look at the &lt;a href=&quot;https://gleam.run/&quot; &gt;Gleam programming language&lt;/a&gt; - it&amp;#39;s great!&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Async TUIs using Bubble Tea</title><link>https://nabeelvalley.co.za/blog/2026/26-03/bubbletea-commands.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/26-03/bubbletea-commands.html</guid><description>Using Bubble Tea commands in Go for snappy TUIs</description><pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Async TUIs using Bubble Tea&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Assumed audience: UI developers, people who program in Go, or anyone just generally interested in making computers to things using code&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There was a little bug I ran into a while back but hadn&amp;#39;t been important enough for me to fix until yesterday when it started to slow me down&lt;/p&gt;
&lt;p&gt;On &lt;a href=&quot;https://github.com/sftsrv/tri&quot; &gt;Tri&lt;/a&gt; - a TUI app I built that is something like if &lt;code&gt;tree&lt;/code&gt; was searchable and had previews like&lt;code&gt;fzf&lt;/code&gt; - I (knowingly) didn&amp;#39;t implement async tasks upfront. At the time I was mostly focused on getting the implementation to a good level of UX and free of bugs. As such, there was a clear slowness when navigating the UI while running slow tasks, such as a &lt;code&gt;git diff&lt;/code&gt; in a large repository&lt;/p&gt;
&lt;p&gt;I sat down yesterday to make the app run previews run in the background - this turned out to be really easy and I thought I&amp;#39;d write about it just to mention why that was the case&lt;/p&gt;
&lt;p&gt;Most TUIs I write in Go use the excellent suite of libraries by &lt;a href=&quot;https://charm.sh/&quot; &gt;Charm&lt;/a&gt; - and in this particular case, the &lt;a href=&quot;https://github.com/charmbracelet/bubbletea&quot; &gt;Bubble Tea TUI framework&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Elm Architecture&lt;/h2&gt;
&lt;p&gt;The Bubble Tea framework is based on the &lt;a href=&quot;https://guide.elm-lang.org/architecture/&quot; &gt;Elm Architecture&lt;/a&gt; which is a functional style pattern for building UIs. I think understanding the Elm architecture is a generally useful and the documentation is worth a read for developers building any kind of user interface (even if it&amp;#39;s not in Elm)&lt;/p&gt;
&lt;p&gt;The core idea is this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;All UI flows from a Model&lt;/li&gt;
&lt;li&gt;Messages are used to perform Updates on the Model&lt;/li&gt;
&lt;li&gt;A View converts the Model into UI&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;This is also known as the MVU pattern (Model -&amp;gt; View -&amp;gt; Update)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using this pattern, we can build a simple implementation of an app that has two bits of independent UI - a counter that increments when the user presses &lt;code&gt;space&lt;/code&gt;, and a task runner that runs some heavy tasks triggered by pressing &lt;code&gt;enter&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;A Sad Implementation&lt;/h2&gt;
&lt;p&gt;A naive implementation of this using Bubble Tea has the following bits that matter for discussion:&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;Update&lt;/code&gt; function, when we press &lt;code&gt;space&lt;/code&gt; we increment the counter, and when we press &lt;code&gt;enter&lt;/code&gt; we run some tasks:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Update&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;msg&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Msg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	case&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KeyPressMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;ctrl+c&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, tea.Quit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;space&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.counter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;enter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.running &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This method then updates the model and returns the updated model - for context, the &lt;code&gt;doTasks&lt;/code&gt; function looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doHeavyWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	t &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; rand.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;IntN&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // irl we&amp;#39;d do something other than sleep&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	time.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; time.Second)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;		doHeavyWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tasks, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{i, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;We can see this running below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/content/blog/2026/26-03/bubbletea-commands-v1.gif&quot; alt=&quot;V1 implementation in action&quot; &gt;&lt;/p&gt;
&lt;p&gt;The problem with the above implementation is twofold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Bad performance - The UI is blocked while the tasks are running, so the counter doesn&amp;#39;t update until after the tasks are run&lt;/li&gt;
&lt;li&gt;Sad UX - There isn&amp;#39;t a way to update an in-progress task, would be nice to not have to wait&lt;/li&gt;
&lt;/ol&gt;
&lt;details&gt;
&lt;summary&gt;You can see the full V1 implementation if you&amp;#39;d like&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; v1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;os&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	tea &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;charm.land/bubbletea/v2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	rand &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;math/rand/v2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; task&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	index &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	done  &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;bool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; model&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	counter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	running &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;bool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	tasks   []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	status &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;busy&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; t.done {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		status &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;done&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sprintf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Task &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%s&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;]&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, t.index, status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; sleepRandomly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	t &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; rand.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;IntN&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	time.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; time.Second)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;		sleepRandomly&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tasks, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{i, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;true&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; initialModel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		counter: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		running: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks:   []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Init&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Update&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;msg&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Msg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	case&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KeyPressMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;ctrl+c&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, tea.Quit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;space&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.counter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;enter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.running &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;View&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;View&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sprintf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;count = &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, m.counter)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; !&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;m.running {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;NewView&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Press space to increment counter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Press enter to start tasks&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	done &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; _, t &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m.tasks {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; !&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.done {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			done &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; t.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	title &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Running Tasks&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; done {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		title &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;All done&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;NewView&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; title &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	p &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;NewProgram&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;initialModel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; _, err &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; p.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(); err &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nil&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Printf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Alas, there&amp;#39;s been an error: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%v&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		os.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Exit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;A Happy Implementation&lt;/h2&gt;
&lt;p&gt;The solution that&amp;#39;s provided by Bubble Tea is to move the IO based work into a &lt;a href=&quot;https://charm.land/blog/commands-in-bubbletea/&quot; &gt;Command&lt;/a&gt;. A command is used to make things async and is handled by the framework&lt;/p&gt;
&lt;p&gt;A command looks like so:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// its type is tea.Cmd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; cmd &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// its value is a function that returns tea.Msg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;cmd &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; () tea.Msg {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  return&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  SomeMessage&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;So in order to make our work async, we simply need to return a &lt;code&gt;tea.Cmd&lt;/code&gt; in our &lt;code&gt;Update&lt;/code&gt; function instead of actually doing all the work&lt;/p&gt;
&lt;p&gt;Instead of defining a function that does the work, we can define one that returns a &lt;code&gt;tea.Cmd&lt;/code&gt; that will do the work:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; taskDoneMsg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	index &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; makeTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() ([]&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; cmds []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tasks, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{i, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		cmds &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(cmds, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Msg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;			doHeavyWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; taskDoneMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{i}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks, cmds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;This will offload the work and we&amp;#39;ll receive a &lt;code&gt;taskDoneMsg&lt;/code&gt; message when the work is done. This also has a nice side effect - by decoupling the creation of the &lt;code&gt;task&lt;/code&gt; and the actual execution of it, we can now track the status of each task as it completes&lt;/p&gt;
&lt;p&gt;We can do that in the &lt;code&gt;Update&lt;/code&gt; function by handling the &lt;code&gt;taskDoneMsg&lt;/code&gt; message as well as returning the &lt;code&gt;[]tea.Cmds&lt;/code&gt; that comes from the &lt;code&gt;makeTasks&lt;/code&gt; function instead of actually doing the work upfront&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Update&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;msg&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Msg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;  // handle updating the model when the task is done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	case&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; taskDoneMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		m.tasks[msg.index].done &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;    return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	case&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KeyPressMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;ctrl+c&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, tea.Quit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;space&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.counter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;enter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.running &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			tasks, cmds &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; makeTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;      // batch the new cmds for bubbletea to handle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Batch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(cmds&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And with that, we&amp;#39;ve now got a responsive UI that lets the counter work even while the tasks are running as well as makes it possible for us to track task state:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/content/blog/2026/26-03/bubbletea-commands-v2.gif&quot; alt=&quot;V2 implementation in action&quot; &gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;You can see the full V2 implementation if you&amp;#39;d like&lt;/summary&gt;&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;package&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;import&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;fmt&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;os&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;	&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;time&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	tea &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;charm.land/bubbletea/v2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	rand &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;math/rand/v2&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; task&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	index &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	done  &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;bool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; taskDoneMsg&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	index &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;t task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	status &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;busy&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; t.done {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		status &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;done&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sprintf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Task &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%s&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;]&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, t.index, status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; doHeavyWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	t &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; rand.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;IntN&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;5&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	time.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sleep&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(time.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Duration&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(t) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;*&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; time.Second)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; makeTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() ([]&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; cmds []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; i &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 10&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(tasks, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{i, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		cmds &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; append&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(cmds, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Msg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;			doHeavyWork&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; taskDoneMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{i}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks, cmds&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; model&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; struct&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	counter &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	running &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;bool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	tasks   []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; initialModel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		counter: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		running: &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;false&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks:   []&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;task&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;{},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Init&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Update&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;msg&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Msg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;Cmd&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.(&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	case&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; taskDoneMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		m.tasks[msg.index].done &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	case&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;KeyPressMsg&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		switch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; msg.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;String&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;ctrl+c&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, tea.Quit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;space&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.counter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;++&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		case&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;enter&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.running &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			tasks, cmds &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; makeTasks&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			m.tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;			return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Batch&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(cmds&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m model&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;View&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;tea&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;.&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;View&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Sprintf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;count = &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%d&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, m.counter)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; !&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;m.running {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;NewView&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Press space to increment counter&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;Press enter to start tasks&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	done &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	for&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; _, t &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; m.tasks {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; !&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;t.done {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;			done &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		tasks &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; t.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	title &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;Running Tasks&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; done {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		title &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;All done&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;NewView&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(count &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; title &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;+&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;\n&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; +&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tasks)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; Run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	p &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; tea.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;NewProgram&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;initialModel&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; _, err &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; p.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Run&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(); err &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nil&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Printf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Alas, there&amp;#39;s been an error: &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%v&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;		os.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Exit&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;/details&gt;&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&amp;#39;s it - no Goroutines or channels needed, a pretty good abstraction on the side of the framework - and minimal effort needed from us&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A small aside, I&amp;#39;ve started working on what will probably be a fairly sizeable side project. As such, I&amp;#39;ve gotten absolutely nothing done on that while somehow managing to put together a few blog posts (this one + &lt;a href=&quot;/blog/2026/22-03/mildly-interesting-eid&quot; &gt;another one about eid&lt;/a&gt; + &lt;a href=&quot;/blog/2026/26-03/tri-x-git-tricks&quot; &gt;another one about tri&lt;/a&gt;), update my photo galleries (&lt;a href=&quot;/photography/places/netherlands&quot; &gt;general nl&lt;/a&gt; and &lt;a href=&quot;/photography/places/2026-winter-netherlands&quot; &gt;stuff from last winter&lt;/a&gt;) on my site, and fix a bunch of random things in other random side projects just this week - oh the power of procrastination&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Git Tricks with Tri and Difft</title><link>https://nabeelvalley.co.za/blog/2026/26-03/tri-x-git-tricks.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/26-03/tri-x-git-tricks.html</guid><pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Git Tricks with Tri and Difft&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Assumed audience: Developers/technical people who use git and/or enjoy terminal UIs (TUIs)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So I finally got &lt;a href=&quot;https://github.com/sftsrv/tri&quot; &gt;&lt;code&gt;tri&lt;/code&gt;&lt;/a&gt; running super fast which &lt;a href=&quot;/blog/2026/26-03/bubbletea-commands&quot; &gt;I already talked about today&lt;/a&gt; and I came across something mildly annoying but not all bad so thought it would be nice to write down&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://difftastic.wilfred.me.uk/introduction.html&quot; &gt;&lt;code&gt;difft&lt;/code&gt;&lt;/a&gt; for my &lt;a href=&quot;https://git-scm.com/&quot; &gt;&lt;code&gt;git&lt;/code&gt;&lt;/a&gt; diffs. This works really nicely as it&amp;#39;s got some syntax awareness and integrates really well into other tools I use such as &lt;a href=&quot;https://github.com/jesseduffield/lazygit/tree/master&quot; &gt;&lt;code&gt;lazygit&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, I&amp;#39;m a &lt;a href=&quot;https://en.wikipedia.org/wiki/Unix_philosophy&quot; &gt;Unix Philosophy&lt;/a&gt; dude so I build &lt;a href=&quot;https://github.com/sftsrv&quot; &gt;my tools&lt;/a&gt; to do the same - so naturally I wanted to use &lt;code&gt;difft&lt;/code&gt; with &lt;code&gt;tri&lt;/code&gt; - so, here&amp;#39;s how to do that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The below examples are using &lt;a href=&quot;https://www.nushell.sh/&quot; &gt;Nushell&lt;/a&gt; so your shell&amp;#39;s exact syntax may vary but the idea is the same&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; diff&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; HEAD&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --name-only&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; GIT_EXTERNAL_DIFF&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;difft --color=always --display=inline&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tri&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --preview&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; diff HEAD &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;--&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Okay, braindump definitely. Realistically, since I want &lt;code&gt;difft&lt;/code&gt; to always behave like this, It&amp;#39;s probably worth setting the environment variable elsewhere, but the steps are basically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the &lt;code&gt;GIT_EXTERNAL_DIFF&lt;/code&gt; environment variable to have the &lt;code&gt;difft&lt;/code&gt; command, this causes git to use the entire command and not just execute the binary provided as with &lt;a href=&quot;https://git-scm.com/docs/diff-config#Documentation/diff-config.txt-diffexternal&quot; &gt;&lt;code&gt;diff.external&lt;/code&gt;&lt;/a&gt;, so I can provide the flags to format &lt;code&gt;difft&lt;/code&gt; as desired&lt;/li&gt;
&lt;li&gt;Then just use &lt;code&gt;tri&lt;/code&gt; as normal&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Assuming you&amp;#39;ve set step 1. within your shell, the command is more simply:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;sh&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# step 1.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$env.GIT_EXTERNAL_DIFF = &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;difft --color=always --display=inline&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;#step 2.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; diff&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; HEAD&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --name-only&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tri&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; --preview&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; diff HEAD &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;--&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Which is just the normal way that &lt;code&gt;tri&lt;/code&gt; works so yay&lt;/p&gt;
&lt;p&gt;And that&amp;#39;s it okbye&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Update 14 April 2026&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#39;ve added this function to my nu config which basically do the above:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;nu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;def&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; &amp;quot;g diff tri&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;range&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; = &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;HEAD..master&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;  git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; diff&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; ($range) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;--&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;name-only&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; GIT_EXTERNAL_DIFF=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;difft --color=always --display=inline&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tri&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; --&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;preview&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; $&amp;quot;git diff (&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$range&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;) -- &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; --&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;flat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;Update 04 May 2026&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#39;ve wanted to do more complex preview behavior with &lt;code&gt;tri&lt;/code&gt; - particularly making it possible to generate custom commands. I&amp;#39;ve recently added support for that so it now makes for some really interesting stuff, like a command for example the below command which lets you browse the input files&amp;#39; history&lt;/p&gt;
&lt;p&gt;Using it looks like this:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;nu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;^find&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; **/*.go&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; |&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; g&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; tri&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the definition is a bit messy, but not too complicated I hope:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;nu&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;# Expects a list of paths as an input&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;def&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; &amp;quot;g log tri&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; [] {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;  $in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; lines&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; par-each&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {|&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;p&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;| &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;git&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; log&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; --&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;pretty&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;=format:&amp;quot;%as %h %f&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;-&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; $p &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;|&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; str replace&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;m&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; -&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;a&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; --&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;regex&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; ^&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; $&amp;quot;(&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;$p&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;)/&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; to text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;  |&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; GIT_EXTERNAL_DIFF=&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;difft --color=always --display=inline&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; tri&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; --&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;preview&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; &amp;quot;git diff $4^..$4 -- $1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; --&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;pattern&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; `^(.*)/((\d|-)+) (\w+)`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;This is also probably very inefficient. So be selective about the paths you provide since this does a log for all given paths and can be very slow on a large repository&lt;/p&gt;
&lt;/blockquote&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Quick and Dirty Object Access in Go</title><link>https://nabeelvalley.co.za/blog/2026/27-03/deep-dynamic-access.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/27-03/deep-dynamic-access.html</guid><pubDate>Fri, 27 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Quick and Dirty Object Access in Go&lt;/h1&gt;&lt;site-markdown&gt;&lt;blockquote&gt;
&lt;p&gt;Assumed audience: Developers/technical people who use Go as a programming language&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This probably isn&amp;#39;t too difficult to write but it&amp;#39;s recursive and I had fun putting it together so here it is&lt;/p&gt;
&lt;p&gt;Basically, I was trying to access a deeply nested object that was parsed from &lt;a href=&quot;https://pkg.go.dev/github.com/BurntSushi/toml&quot; &gt;BurntSushi/toml&lt;/a&gt; in some generic fashion and it was getting annoying to constantly cast things and do the necessary checks at every level so I made two utilities that can access nested data a bit more conveniently&lt;/p&gt;
&lt;p&gt;First off, here&amp;#39;s a helper type to sprinkle around:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;type&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; dynamic&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; =&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; map&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;[&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;any&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Then, here&amp;#39;s the version that will panic if it hits something it&amp;#39;s not expecting:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; unsafeIndex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; dynamic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ...&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; len&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(path) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	inner &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data[path[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; len&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(path) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; inner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; unsafeIndex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(inner.(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dynamic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;), path[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And the version that returns the appropriate errors along the way:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;func&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; safeIndex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;data&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt; dynamic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;path&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; ...&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;string&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) (&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;any&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;error&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; len&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(path) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	inner, ok &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data[path[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;0&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; !&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;ok {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; data, fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Error indexing path &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%v&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; for &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%v&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, path, data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; len&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(path) &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;==&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; 1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; inner, &lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	dyn, ok &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; inner.(&lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dynamic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	if&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt; !&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;ok {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;		return&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; dyn, fmt.&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;Errorf&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;Error indexing into inner struct &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%v&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt; for &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;%v&lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, path, inner)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;	}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;	return&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; safeIndex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(dyn, path[&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt;1&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;:]&lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;...&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;Using them is also fairly normal, as seen below:&lt;/p&gt;
&lt;figure class=&quot;codeblock&quot; &gt;&lt;pre tabindex=&quot;0&quot; class=&quot;shiki shiki-themes github-light-high-contrast github-dark-high-contrast&quot; style=&quot;background-color:#ffffff;--shiki-dark-bg:#0a0c10;color:#0e1116;--shiki-dark:#f0f3f6&quot; lang=&quot;go&quot; &gt;&lt;code&gt;&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#66707B;--shiki-dark:#BDC4CC&quot; &gt;// whatever you&amp;#39;re doing to decode the data. e.g. JSON/TOML parser&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;var&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; output &lt;/span&gt;&lt;span style=&quot;color:#702C00;--shiki-dark:#FFB757&quot; &gt;dynamic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;decodeData&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(FILE_CONTENT, &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;output)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;dynamicSources, err &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;:=&lt;/span&gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt; safeIndex&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(output, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;some&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;deeply&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;nested&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;, &lt;/span&gt;&lt;span style=&quot;color:#032563;--shiki-dark:#ADDCFF&quot; &gt;&amp;quot;property&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;if&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; err &lt;/span&gt;&lt;span style=&quot;color:#A0111F;--shiki-dark:#FF9492&quot; &gt;!=&lt;/span&gt;&lt;span style=&quot;color:#023B95;--shiki-dark:#91CBFF&quot; &gt; nil&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#622CBC;--shiki-dark:#DBB7FF&quot; &gt;    panic&lt;/span&gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;(err)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;span style=&quot;color:#0E1116;--shiki-dark:#F0F3F6&quot; &gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot; &gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Photos from the Nederlands Fotomuseum</title><link>https://nabeelvalley.co.za/blog/2026/28-03/nederlands-fotomuseum.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/28-03/nederlands-fotomuseum.html</guid><pubDate>Sat, 28 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Photos from the Nederlands Fotomuseum&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;We went to the &lt;a href=&quot;https://nederlandsfotomuseum.nl&quot; &gt;Nederlands Fotomuseum&lt;/a&gt; which was really great. I resisted the urge to take any pictures in the museum but when I got to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyanotype&quot; &gt;Cyanotype&lt;/a&gt; exhibit I couldn&amp;#39;t resist. You can see some of the pictures below&lt;/p&gt;
&lt;p&gt;Also, they had this really cool digital gallery thingy so here&amp;#39;s a video of that!&lt;/p&gt;
&lt;video controls=&quot;&quot; muted=&quot;&quot; alt=&quot;2026-03-28 - Nederlands Fotomuseum Gallery Lens Demo&quot; width=&quot;100%&quot; &gt;
  &lt;source src=&quot;/content/blog/2026/28-03/2026-03-28 - Nederlands Fotomuseum Gallery Lens Demo.MOV&quot; &gt;
&lt;/video&gt;&lt;p&gt;I also saw this silly bus which turned out to be one of &lt;a href=&quot;https://nl.wikipedia.org/wiki/Splashtours&quot; &gt;these water bus things&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/content/blog/2026/28-03/2023-03-28%20-%20Water%20bus.JPG&quot; alt=&quot;Water bus&quot; &gt;&lt;/p&gt;
&lt;p&gt;Then on the train ride home I watched about 8 people look at a seat, have a weird facial expression and walk away, not sitting on the chair &lt;/p&gt;
&lt;p&gt;Zahrah pointed out that there was a sticky note on the chair saying it was wet (I couldn’t see the note)&lt;/p&gt;
&lt;p&gt;At some point an old man came along, looked perplexingly at the note, and decided to touch it and was like - this is not wet?&lt;/p&gt;
&lt;p&gt;The man across said, yeah it doesn&amp;#39;t look wet but I don’t know&lt;/p&gt;
&lt;p&gt;The old man sat on the seat next to the labeled-as-wet one&lt;/p&gt;
&lt;p&gt;People continued to walk past and look at the sticky note and walk away&lt;/p&gt;
&lt;p&gt;The old man moved the sticky note away, this was either to state that the seat is in fact not wet - or as an effort to prank someone by making them sit on a wet seat&lt;/p&gt;
&lt;p&gt;We do not know&lt;/p&gt;
&lt;p&gt;Zahrah had some comments about how everyone was appealing to the authority of the sticky note and how much that says about the fragility of the social contract&lt;/p&gt;
&lt;p&gt;IDK I was just sitting and laughing every time anyone walked past because it was funny&lt;/p&gt;
&lt;p&gt;Anyways ... here are the pictures then!&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2023-03-28---i16---color---NL---Rotterdam---Double-projector-with-alternating-slits.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2023-03-28 - i16 - color - NL - Rotterdam - Double projector with alternating slits&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2023-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Double%20projector%20with%20alternating%20slits.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Blurry-person-in-front-of-all-of-cyanotype-prints.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Blurry person in front of all of cyanotype prints&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Blurry%20person%20in%20front%20of%20all%20of%20cyanotype%20prints.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Cyanotypes-from-Dutch-colonization-times-printed-on-cloth.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Cyanotypes from Dutch colonization times printed on cloth&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Cyanotypes%20from%20Dutch%20colonization%20times%20printed%20on%20cloth.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Cyanotypes-of-plants.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Cyanotypes of plants&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Cyanotypes%20of%20plants.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Cyanotypes-of-plastic-found-in-the-ocean.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Cyanotypes of plastic found in the ocean&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Cyanotypes%20of%20plastic%20found%20in%20the%20ocean.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Cyanotypes-of-still-lifes-on-table-cloths.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Cyanotypes of still lifes on table cloths&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Cyanotypes%20of%20still%20lifes%20on%20table%20cloths.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Full-sized-cyanotypes-of-people-printed-on-cloth.html&quot; &gt;&lt;img aspect-ratio=&quot;1.5003750937734435&quot; orientation=&quot;horizontal&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Full sized cyanotypes of people printed on cloth&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Full%20sized%20cyanotypes%20of%20people%20printed%20on%20cloth.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-28---nederlands-fotomuseum/2026-03-28---i16---color---NL---Rotterdam---Sunlight-on-side-of-building-interior-with-staircases-criss-crossing.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-28 - i16 - color - NL - Rotterdam - Sunlight on side of building interior with staircases criss-crossing&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-28%20-%20nederlands%20fotomuseum/2026-03-28%20-%20i16%20-%20color%20-%20NL%20-%20Rotterdam%20-%20Sunlight%20on%20side%20of%20building%20interior%20with%20staircases%20criss-crossing.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item><item><title>Symbols on the Ground</title><link>https://nabeelvalley.co.za/blog/2026/31-03/mural-on-the-ground.html</link><guid isPermaLink="true" >https://nabeelvalley.co.za/blog/2026/31-03/mural-on-the-ground.html</guid><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;main&gt;&lt;article class=&quot;site-article&quot; &gt;&lt;h1&gt;Symbols on the Ground&lt;/h1&gt;&lt;site-markdown&gt;&lt;p&gt;I came across some random murals on the along the path in Utrecht today. A while later when walking by I stopped to take some pictures of them - I saw 15. But according to &lt;a href=&quot;https://mozaiekmonumenten.nl/portfolio/exclusief-in-opdracht/&quot; &gt;Mozaiek Monumenten&lt;/a&gt; there are 17 - I guess I the remaining two were in the construction site just past the 15th&lt;/p&gt;
&lt;p&gt;They&amp;#39;re a reference to the &lt;em&gt;Sustainable Development Goals&lt;/em&gt;. The reference from Mozaiek Monmumenten can be seen below with the descriptions of each of them:&lt;/p&gt;
&lt;p&gt;&lt;img aspect-ratio=&quot;1.4997000599880024&quot; orientation=&quot;horizontal&quot; alt=&quot;sdg-legend&quot; src=&quot;/optimized-images/public/content/blog/2026/31-03/sdg-legend.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;You can see the pictures I took of them below:&lt;/p&gt;
&lt;site-gallery&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---01-No-Poverty.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 01 No Poverty&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2001%20No%20Poverty.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---02-No-Hunger.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 02 No Hunger&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2002%20No%20Hunger.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---03-Good-Health.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 03 Good Health&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2003%20Good%20Health.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---04-Quality-Education.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 04 Quality Education&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2004%20Quality%20Education.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---05-Gender-Equality.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 05 Gender Equality&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2005%20Gender%20Equality.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---06-Clean-Water.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 06 Clean Water&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2006%20Clean%20Water.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---07-Sustainable-Energy.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 07 Sustainable Energy&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2007%20Sustainable%20Energy.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---08-Fair-Work.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 08 Fair Work&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2008%20Fair%20Work.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---09-Industry,-Innovation,-and-Infrastructure.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 09 Industry, Innovation, and Infrastructure&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2009%20Industry%2C%20Innovation%2C%20and%20Infrastructure.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---10-Less-Inequality.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 10 Less Inequality&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2010%20Less%20Inequality.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---11-Sustainable-Cities.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 11 Sustainable Cities&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2011%20Sustainable%20Cities.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---12-Responsible-Consumption-and-Production.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 12 Responsible Consumption and Production&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2012%20Responsible%20Consumption%20and%20Production.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---13-Climate-Action.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 13 Climate Action&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2013%20Climate%20Action.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---14-Life-in-Water.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 14 Life in Water&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2014%20Life%20in%20Water.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;site-gallery-image&gt;&lt;a href=&quot;/photography/photo/blog/2026-03-31---symbols-on-the-ground/2026-03-32---i16---color---NL---Utrecht---15-Life-on-Land.html&quot; &gt;&lt;img aspect-ratio=&quot;0.6666666666666666&quot; orientation=&quot;vertical&quot; alt=&quot;2026-03-32 - i16 - color - NL - Utrecht - 15 Life on Land&quot; src=&quot;/optimized-images/content/photography/blog/2026-03-31%20-%20symbols%20on%20the%20ground/2026-03-32%20-%20i16%20-%20color%20-%20NL%20-%20Utrecht%20-%2015%20Life%20on%20Land.webp&quot; &gt;&lt;/a&gt;&lt;/site-gallery-image&gt;&lt;/site-gallery&gt;&lt;p&gt;The two that I don&amp;#39;t have are:&lt;/p&gt;
&lt;ol start=&quot;16&quot; &gt;
&lt;li&gt;Freedom, Safety, and Strong Public Services&lt;/li&gt;
&lt;li&gt;Partnership for the Goals&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay that&amp;#39;s it, I should walk around with my eyes open more often&lt;/p&gt;&lt;/site-markdown&gt;&lt;/article&gt;&lt;/main&gt;</content:encoded></item></channel></rss>