<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[thoughts & experiments]]></title><description><![CDATA[Random technical endeavors in the AI and web space.]]></description><link>https://blog.shahzeb.co</link><image><url>https://substackcdn.com/image/fetch/$s_!ex65!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43722532-3f2c-40eb-ad4f-4661df00d0a8_1200x1200.png</url><title>thoughts &amp; experiments</title><link>https://blog.shahzeb.co</link></image><generator>Substack</generator><lastBuildDate>Sun, 19 Apr 2026 01:10:54 GMT</lastBuildDate><atom:link href="https://blog.shahzeb.co/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Shahzeb]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[shahzebdev@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[shahzebdev@substack.com]]></itunes:email><itunes:name><![CDATA[Shahzeb]]></itunes:name></itunes:owner><itunes:author><![CDATA[Shahzeb]]></itunes:author><googleplay:owner><![CDATA[shahzebdev@substack.com]]></googleplay:owner><googleplay:email><![CDATA[shahzebdev@substack.com]]></googleplay:email><googleplay:author><![CDATA[Shahzeb]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Pretend The Internet Isn't Infinite]]></title><description><![CDATA[Be more present in the moment and less present on your phone.]]></description><link>https://blog.shahzeb.co/p/pretend-the-internet-isnt-infinite</link><guid isPermaLink="false">https://blog.shahzeb.co/p/pretend-the-internet-isnt-infinite</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Sat, 27 Sep 2025 21:32:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/987f5006-f483-4c17-9f93-b5c7025a8d8c_1600x1123.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Phf0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Phf0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Phf0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Phf0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Phf0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Phf0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg" width="1456" height="1022" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1022,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:609556,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.shahzeb.co/i/174711712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Phf0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Phf0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Phf0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Phf0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9df953d7-9867-4046-8280-e157a874a955_1600x1123.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Studio Interior by William Merritt Chase c. 1882</figcaption></figure></div><p>Your attention span is being stripped for parts and sold for scrap metal. From content whiplash before we&#8217;ve gotten out of bed to feeling like we&#8217;re in a daze when it&#8217;s bedtime. The glass screen in our pocket has put us in a self-induced psychosis. I&#8217;ve spent the summer unraveling this mess.</p><p>Newsfeeds and content feeds are designed for one thing: warping your sense of time. When I take the train to work in the morning I notice how almost everyone is flicking up on Instagram Reels or TikTok. This is because the act of doing something mundane like traveling between point A to point B on public transport is dampened by these apps. It&#8217;s time dilation in play. </p><p>We never need to know peace or boredom. This is a betrayal to ourselves. The quiet gaps in our day which might&#8217;ve resulted in an original thought are now filled with the consumption of mental junk food. Charles Darwin would work for two 90 min periods and then go on two separate 60 min walks. No AirPods, no productivity podcasts, no Newsfeeds. Just his own thoughts and a groundedness in the present moment. </p><p>I don&#8217;t blame us. It&#8217;s a bit like handing a cigarette to a 15 year old and never mentioning the downsides. The biggest problem is that the content on these apps is endless. The days of early Facebook where our timelines were filled with people we know is long behind us. </p><blockquote><p>Netflix&#8217;s biggest competition is sleep. <em>- Netflix CEO Reed Hastings.</em></p></blockquote><p>This isn&#8217;t where I recap my summer of living with a dumb phone and deleting all social media profiles. Becoming a Luddite is unrealistic. I have no affinity for a cold Cabin life in Lincoln, Montana. Instead this summer I focused on narrowing the amount of available content. I used ad-block extensions to &#8220;delete&#8221; parts of the web apps that felt endless. My YouTube homepage is a black page, the subscriptions and YouTube shorts tabs are all deleted. If I want to watch a video I need to seek it out by searching for it rather than being nudged by the <em>Algorithm Overlords.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pIl5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pIl5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 424w, https://substackcdn.com/image/fetch/$s_!pIl5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 848w, https://substackcdn.com/image/fetch/$s_!pIl5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 1272w, https://substackcdn.com/image/fetch/$s_!pIl5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pIl5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png" width="1456" height="972" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:972,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:460879,&quot;alt&quot;:&quot;YouTube homepage with no content. Just an empty page.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.shahzeb.co/i/174711712?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="YouTube homepage with no content. Just an empty page." title="YouTube homepage with no content. Just an empty page." srcset="https://substackcdn.com/image/fetch/$s_!pIl5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 424w, https://substackcdn.com/image/fetch/$s_!pIl5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 848w, https://substackcdn.com/image/fetch/$s_!pIl5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 1272w, https://substackcdn.com/image/fetch/$s_!pIl5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16c1a635-fcbc-465d-bf92-2a68f0df9e21_2190x1462.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">My not endless YouTube</figcaption></figure></div><p>By killing my infinite feeds, I quickly run out of content to consume. I&#8217;m forced to fill the gaps of time in other ways. There are 8 or so creators I truly care for and I have post notifications on for them. This feels like the <em>old internet</em> when RSS readers would push you content you actually wanted.</p><p>By spending less time in the digital realm, I feel more present in the physical one. I&#8217;m discovering the dwindling art of talking to strangers, reading more books, and spending more time slowly shuffling through unorganized bins of vinyl records. I&#8217;ve made a trade. I&#8217;m less online but have more vibrant days.</p><p>How much of the furniture in your home just randomly appeared one day? Probably none. Almost all of it was curated by you over time. We wouldn&#8217;t clutter our homes with random furniture so why are we allowing <em>BigCrops</em> to clutter our minds? </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">I might do more non-technical essays. Come along for the ride:</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Earning the right to finish.]]></title><description><![CDATA[The following are March 2025 reflections as I build a thing. Dev log &#176;4.]]></description><link>https://blog.shahzeb.co/p/earning-the-right-to-finish</link><guid isPermaLink="false">https://blog.shahzeb.co/p/earning-the-right-to-finish</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Mon, 07 Apr 2025 16:03:18 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/be14bbbc-b523-4f72-81d0-72383ddaa422_420x300.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Dear Reader, the thing I&#8217;ve been building the last few months is finally done. I earned the right to finish.</p><h1>Introducing: Coffee Engineering &#9749;&#65039;</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6t-h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6t-h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 424w, https://substackcdn.com/image/fetch/$s_!6t-h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 848w, https://substackcdn.com/image/fetch/$s_!6t-h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 1272w, https://substackcdn.com/image/fetch/$s_!6t-h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6t-h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png" width="1456" height="947" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:947,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;coffee.engineering screenshot&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="coffee.engineering screenshot" title="coffee.engineering screenshot" srcset="https://substackcdn.com/image/fetch/$s_!6t-h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 424w, https://substackcdn.com/image/fetch/$s_!6t-h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 848w, https://substackcdn.com/image/fetch/$s_!6t-h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 1272w, https://substackcdn.com/image/fetch/$s_!6t-h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb216309a-436b-4410-93b4-fb5ff10f8569_2542x1654.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I&#8217;ll keep it short because I know your time is valuable. It&#8217;s called Coffee Engineering and it lives on: <a href="https://coffee.engineering/?utm_source=blog">coffee.engineering</a>. The tagline is &#8220;caffeine for AI&#8221; (fun right?). And the SEO optimized description is &#8220;coffee engineering is a tool to create, share, and manage your AI prompts and agents in a simple, easy-to-use no-code way&#8221;. </p><p>Few nights ago I was having a conversation with my brother. He mentioned sometimes you just have an itch you need to scratch. A landscape in your mind that needs to put onto canvas. A conversation between two friends that needs to be turned into a short story. A little product idea that needs to not die on the cutting room floor. Coffee Engineering is an itch I just had to scratch, and I&#8217;m glad I did.</p><p>&#128192; If you&#8217;re a visual learner and not a reader, I have a neat <a href="https://youtu.be/5NVJL9VjaYI">demo on YouTube</a>.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://youtu.be/5NVJL9VjaYI&quot;,&quot;text&quot;:&quot;Watch Demo Video&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://youtu.be/5NVJL9VjaYI"><span>Watch Demo Video</span></a></p><h4>Observation: prompts are repetitive </h4><p>I often go to ChatGPT or Claude and say:</p><ol><li><p>You&#8217;re a senior React software engineer using Tanstack Router and Material UI v6, give me code that does X.</p></li><li><p>Give me a list of 5 movies similar to movie Y, include director and year in the response.</p></li><li><p>Research X and give me a table that includes name, app, cost. </p></li></ol><p>Prompts tend to be repetitive. </p><h4>Observation: people want to share their prompts</h4><p>I know there are entire Discord, Reddit, and Facebook communities for people trying to squeeze the most out of large language models. A member (who might not be too tech savvy) will ask &#8220;what is the best way to analyze this CSV&#8221; and some other member will reply with a Pastebin or Github gist link saying &#8220;this is the prompt I use.&#8221; </p><p>There are also technical communities like the <a href="https://cursor.directory/">Cursor Directory</a> where people are sharing prompt files you&#8217;re expected to copy-and-paste into your code editor.</p><p>In all these communities the expectation is that people float around these text files like loose pieces of paper and copy-and-paste them into AI services. Seems a bit inefficient no?</p><h4>Observation: more copying-and-pasting</h4><p>I know Claude is good at code. I know ChatGPT is good at more high level thinking. Sometimes I&#8217;ll ask ChatGPT something and then copy and paste that response into Claude and ask it for more details. Hmm&#8230; if only there was a more cleaver way to switch in and out of different models while preserving the context.</p><h4>Observation: Projects and Custom GPTs</h4><p>Some of what I&#8217;ve built can be achieved with <a href="https://www.anthropic.com/news/projects">Claude Projects</a> or <a href="https://openai.com/index/introducing-gpts/">Custom GPTs</a>. When I started working on Coffee Engineering these products didn&#8217;t exist. I do think I&#8217;ve pushed them further in some ways and made them much more accessible.</p><h4>Observation: why is there only one prompt?</h4><p>Every &#8220;Custom GPT&#8221; style product lets you add some context (from files or in the system prompt) and then the user interacts with it in the same manner: using a single text box. </p><p>I wanted to rethink this. Why can&#8217;t I have 3 inputs? One is the usual prompt, another is a toggle that chooses whether the AI response should include Emoji&#8217;s, and another to choose which language the response should be in. This is what I&#8217;m calling <em>caffeinated prompts</em>. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe to posts about Coffee as I build it:</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><h4>Beans</h4><p>Beans are little self contained <em>things</em> (I refuse to call them &#8220;agents&#8221;) that have context built in. (This is where the <a href="https://youtu.be/5NVJL9VjaYI">visual demo</a> might help). </p><ol><li><p>You build a Bean by giving a short description of what they do. Example: &#8220;A Bean that returns a list of 5 movies similar to the one provided&#8221;</p></li><li><p>We take the user description and turn it into a system prompt using best practices and providing better output shape when appropriate</p></li><li><p>You save it as a public bean called &#8220;Movie Recommender&#8221; and it becomes accessible on &#8220;coffee.engineering/@shahzeb/movies&#8221;</p></li><li><p>Open the Bean, type in <em>Interstellar</em> hit go and boom everything works. </p></li><li><p>Share the Bean&#8217;s link with your mom and now you&#8217;re both watching the <em>Martian</em></p></li></ol><p>I have a Bean to give me <a href="https://svelte.dev/blog/svelte-5-is-alive">Svelete 5</a> code (which is a frontend framework Coffee is built using). I first ask it for a high level project overview using GPT-4 and then in the same thread I switch to Claude and keep the conversation going. If I don&#8217;t like the output a model gave me, with one click I can regenerate the output either using a different model or different temperature (how creative or accurate).</p><p>I can search public Beans. My dad made a fun public Bean and I can just search and use it. Search results are ranked by popularity. Naturally, the most subscribed to Beans bubble to the top. This means that Beans marketplace (aka search) self select for better Beans.</p><p>I&#8217;m learning Spanish right now (shout out to an almost 350 day Duolingo streak). I have a Spanish translation bean. I can right click on a different Bean&#8217;s response and select &#8220;Send Response&#8221; and select the Spanish Bean. So one Bean just sends its output to another. So easy. No copy-and-pasting.</p><p>You can also invoke multiple different Beans from your dashboard at the same time. I&#8217;ve not seen anyone else do this. That&#8217;s why the Coffee Engineering homepage doesn&#8217;t look like the other AI company&#8217;s.</p><p>I&#8217;ve poured a lot of love into the experience of Coffee Engineering. Right click on a movie name from the above Movies Bean and you can search Letterboxd or Wikipedia straight from the right-click menu. The product was not vibe coded. That&#8217;s why it has been in the works for a while. I&#8217;m confident I&#8217;m doing things that even the <em>big boys</em> with trillion-dollar evaluations are not.</p><p>It is currently free. Sign up and I&#8217;ll add you to the beta user list: </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://coffee.engineering/?utm_source=blog&quot;,&quot;text&quot;:&quot;Go to Coffee Engineering&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://coffee.engineering/?utm_source=blog"><span>Go to Coffee Engineering</span></a></p><p>It feels really good to earn the right to finish. Not many creative side projects make it this far. The foundation is set and I know there&#8217;s a ton I can build on top of this. But now I want to earn the right to build those things. </p><p>My next goal is to get 100 users.</p>]]></content:encoded></item><item><title><![CDATA[Continuing the journey]]></title><description><![CDATA[The following are Jan and Feb 2025 reflections as I build a thing. Dev log &#176;3.]]></description><link>https://blog.shahzeb.co/p/continuing-the-journey</link><guid isPermaLink="false">https://blog.shahzeb.co/p/continuing-the-journey</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Tue, 04 Mar 2025 23:52:29 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a0502821-c2d8-428e-9de0-884a5cdee303_420x300.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The following is a blogpost on learnings as I build a <em>thing </em>in my Monthly Dev Log <a href="https://blog.shahzeb.co/t/monthly-dev-log">series</a>.</p><h2>Writing is accountability</h2><p>Even if it&#8217;s without an audience. Let me explain.</p><p>There was very little progress on my project in January so I ended up skipping the post. Things were more productive in Feb hence this blogpost. Also, I&#8217;ve been reflecting on <em>the act of writing.</em></p><p>I think writing is the only thing I find harder than pure software development. In trying to gather my personal notes into something that&#8217;ll be fruitful for an audience, I find my neurons lighting up like little LED light bulbs. Now truth be told, considering I have an audience of a few subscribers, I mostly write these monthly reflections for myself. </p><p>Knowing that at the end of the month I&#8217;ll need to share things I learned forces me to keep momentum. That was my lesson from January. Since there wasn&#8217;t much to share, there was no devlog post. But it didn&#8217;t feel nice break my little monthly streak. Lesson learned. Always make progress and share it regardless of scope. Onwards.</p><h2>Product development is frontend development</h2><p>Admittedly, things are behind where I had anticipated, and I think I have a diagnosis.</p><p>Backend engineering is much easier than frontend engineering. I think there are 2 reasons for this:</p><ol><li><p>You can always make the frontend better. There&#8217;s always some little corner of your product that you can perfect down to the pixel. Backends (especially those that are pre-customer and hence pre-scale) don&#8217;t have this problem. After an API endpoint or some backend infrastructure is functional, it&#8217;s effectively done. The frontend is never done.</p></li><li><p>Frontend engineering is mostly subjective, not objective. This is closely related to the previous point. When you create an API endpoint, you can unit test it for correctness. With a new UI that&#8217;s truly doing something innovative, how do you unit test it for correctness? I don&#8217;t mean a snapshot test or a test to make sure the correct elements are rendered to the screen, I mean, that the<em> users will know it&#8217;s correct.</em></p></li></ol><p>If you&#8217;ve experienced the above listed symptoms then you might be in a kind of product development hell. It&#8217;s a hell of our own creation, and there might be a solution.</p><h2>Leave things on the cutting floor</h2><p>The remedy is simple: accept that things might not be perfect. Realize that doing refactors when there are 0 users is a waste of time. Realize that trying to design component in a perfect reusable fashion only to never re-use them was wasted effort.</p><p>I propose a kind of Occam's razor of product development: if I didn&#8217;t change or fix it, would anyone complain? Often the answer is no.</p><p>The above frame of thinking has helped me push through some challenging UI issues on my solo development journey. Not only does this help in prioritization but I&#8217;ve decided to cut entire features out of the first version of my product. Getting out there is more important than never getting out there but having a few more half-baked features.</p><p>Hoping to release the beta version of my product end-of-month. Keen to share it.</p>]]></content:encoded></item><item><title><![CDATA[All you need is attention.]]></title><description><![CDATA[The following are December reflections as I build a thing. Dev log &#176;2.]]></description><link>https://blog.shahzeb.co/p/all-you-need-is-attention</link><guid isPermaLink="false">https://blog.shahzeb.co/p/all-you-need-is-attention</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Wed, 01 Jan 2025 21:55:39 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7dd6102c-b517-4408-b853-d89e7bc047f8_420x300.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blogpost has almost nothing to do with AI, instead, the following are December reflections as I build a <em>thing </em>in my Monthly Dev Log <a href="https://blog.shahzeb.co/t/monthly-dev-log">series</a>.</p><h2>The back and forth</h2><p><a href="https://blog.shahzeb.co/p/beginning-a-thing">Last month</a> was all about getting a functional MVP. This required me to switch back-and-froth between the backend and the frontend to make sure everything was working. This month required a change of strategy.</p><p>There are two ways of thinking about progress. If you&#8217;re an artist trying to improve your craft, you might choose to work on the skill of painting and the skill of ceramics in a given month. Or you can fully commit to just improving ceramics. Both strategies are going to result in progress but there&#8217;s a different cost associated with each strategy.</p><p>Last month I got the MVP running, this month I decided to change strategy on making progress. The back-and-forth between implementing a backend endpoint and then switching gears to the frontend UI task just didn&#8217;t feel right. The context switching wasn&#8217;t resulting in the type of progress I wanted.</p><p>I completed all my forecasted goals and I think choosing to just work on one craft (backend) this month paid off.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZzMe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZzMe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ZzMe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ZzMe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ZzMe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZzMe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg" width="497" height="493" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:493,&quot;width&quot;:497,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20156,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZzMe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ZzMe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ZzMe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ZzMe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e9f70b-b8d2-424d-8591-3c2aab9bd6a5_497x493.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">It doesn&#8217;t need to be like this.</figcaption></figure></div><h2>It&#8217;s a Sisyphean task</h2><p>The act of building something is the act of getting to know oneself. The more progress you make, the more blind spots you reveal. It&#8217;s easy to get overwhelmed by the seemingly endless todo tasks. Here&#8217;s one strategy I started at the start of this month that will help.</p><p>Make a document and write down &#8220;Version 1&#8221; at the top. Add a table bellow with the following columns: a short description of the feature, a &#8220;page&#8221; column that links to more details about that feature, and a &#8220;status&#8221; column that tracks the progress or completion. I use Obsidian, here&#8217;s an example if I was building a blogging platform:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rr0d!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rr0d!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 424w, https://substackcdn.com/image/fetch/$s_!rr0d!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 848w, https://substackcdn.com/image/fetch/$s_!rr0d!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 1272w, https://substackcdn.com/image/fetch/$s_!rr0d!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rr0d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png" width="1174" height="938" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:938,&quot;width&quot;:1174,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:114598,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rr0d!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 424w, https://substackcdn.com/image/fetch/$s_!rr0d!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 848w, https://substackcdn.com/image/fetch/$s_!rr0d!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 1272w, https://substackcdn.com/image/fetch/$s_!rr0d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc059cfda-7006-460e-b662-125ee47a9b6d_1174x938.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Track your Goals.</figcaption></figure></div><p>Each one of those high-level features get their own document. You don&#8217;t need to conform to any template for these documents, you just jot down what it would take for that feature to be complete. If we click on `feature- draft posts` we might see this document:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZvZh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZvZh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 424w, https://substackcdn.com/image/fetch/$s_!ZvZh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 848w, https://substackcdn.com/image/fetch/$s_!ZvZh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 1272w, https://substackcdn.com/image/fetch/$s_!ZvZh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZvZh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png" width="1456" height="721" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:721,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:108588,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZvZh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 424w, https://substackcdn.com/image/fetch/$s_!ZvZh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 848w, https://substackcdn.com/image/fetch/$s_!ZvZh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 1272w, https://substackcdn.com/image/fetch/$s_!ZvZh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51c1502a-2e28-4c9a-8932-3a2e8796290d_1506x746.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Track subtasks for specific goals.</figcaption></figure></div><p>Now, not only do you know when your product Version 1 will be ready for release, but you can break down the individual features into items that will be easy to conquer. Feature creep can also be prevented because you have a roadmap for this particular release.</p><p>Maybe now, <em>one must imagine Sisyphus happy</em>.</p><h2>The push and pull of simplicity</h2><p>I&#8217;ve been dabbling with <a href="https://www.cursor.com/">Cursor</a>. A code editor that has &#8220;AI code generation&#8221; built into it. It&#8217;s really impressive when it comes to boilerplate code generation. I won&#8217;t lie it is impressive but I think the hardest parts of product development still require the creator to do some deep thinking and problem solving.</p><p>Here are some shortcomings of AI code generation tools:</p><ol><li><p>If you&#8217;re unfamiliar with your own code or tools, then AI will trick you. You need familiarity with your tools to build the intuition to pick up on possibly incorrect AI output.</p></li><li><p>Personal skill atrophy: probably the biggest risk of these tools. You&#8217;ll forget the skill of programming and become a &#8220;prompt engineer&#8221;. Maybe this is the future? I&#8217;m not sure. I need to reflect a bit more on this.</p></li><li><p>Complexity will slip in and you won&#8217;t even realize it. I asked Cursor to generate some boilerplate Stripe Billing checkout code and it created code with 3 different pricing tiers. Billing is complex and if I choose to blindly accept 3 different pricing tiers because my codegen tool outputted it, then I take on serious maintenance and technical debt risk.</p></li></ol><p>Often the most elegant solutions are ones you need to think about. Solutions that can&#8217;t be generated regardless of large context windows.</p><h2>Pricing a product is an art not a science</h2><p>This is the first thing I&#8217;ll ship that&#8217;ll have at least one priced tier. This month was the first time I created a Stripe account and started to read up pricing strategies for digital products. It turns out that pricing isn&#8217;t an exact science.</p><p>One of the first things I did was ask Claude and GPT to assist with a pricing strategy. They&#8217;re kind of bad at this task. In part because they choose complexity (see previous section) or maybe they&#8217;re just bad at math.</p><p>I learnt that nothing beats a simple Excel file. Track the parts that&#8217;ll cost and then add a margin on top of it. Stripe has a lot of bells and whistles (do you want users to have free trials? coupons? monthly vs. annual discounts?). My recommendation is to start things simple. The more layers of billing code you add, the more time you&#8217;ll spend moonlighting as a &#8220;billing engineer&#8221;.</p><p>I did gain one important insight in my readings: price things higher than you&#8217;re comfortable with. Reducing the price is easier than increasing it.</p><h2>Boredom is a feature, not a bug</h2><p>December is a sleepy month. The perfect month to watch Japanese film <em><a href="https://www.youtube.com/watch?v=QzZBbX5A1FA">Perfect Days</a></em> that highlights a character in Tokyo finding the beauty in a simple life. I think we can all learn from this film. </p><p>In order to make progress all you need is attention. But at the same time, some of the best insights will not come when you&#8217;re sitting in front of your code-editor. Going on walks. Writing (which is perhaps the only thing I find harder than coding). And just having other hobbies is a crucial part of making progress.</p><p>Happy New Year. Talk to you in a month my friend.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading thoughts &amp; experiments! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Beginning a thing.]]></title><description><![CDATA[The following are November reflections as I build a thing. Dev log &#176;1.]]></description><link>https://blog.shahzeb.co/p/beginning-a-thing</link><guid isPermaLink="false">https://blog.shahzeb.co/p/beginning-a-thing</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Mon, 02 Dec 2024 21:12:28 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/660a3b79-02b2-4b27-b9de-a0d0eeb9551f_420x300.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The following are November reflections as I build a <em>thing</em>.</p><h2>Your domain is about to expire</h2><p>A month ago I received an email from Vercel telling me that my domain was about to expire. Getting a domain expiration email always feels embarrassing. It's an unexpected reminder of what could've been. You recall a year ago when you ran `npx create-react-app world-changing-idea` only to forget about it 3 days later.</p><p>The crossroads: let the domain disappear into the ether like it never happened, or renew? Let's renew.</p><h2>The proof is in the weekend</h2><p>One of my favorite essays is "<a href="https://learnhowtolearn.org/how-to-build-extremely-quickly/?utm_source=pocket_shared">How to Build Anything Extremely Quickly</a>". The gist is simple: outline the tasks and speed run them. A complicated task? Break it up into smaller tasks. Speed run those.</p><p>I used this method to build a weekend prototype of the core functionality of the <em>thing</em>. No SAAS landing page, no login, or database. Just a simple frontend with one component that hits a single <a href="https://hono.dev/">Hono</a> endpoint. It just works. This proved to me that <em>thing</em> could in fact be a functional product.</p><h2>Don't obsess about your knives</h2><p>There's a tendency in software engineering to obsess about our tools. Our stacks. Our frameworks. Our <a href="https://neovim.io/">Neovim</a> or <a href="https://obsidian.md/">Obsidian</a> configs. I think tooling matters, but time spent perfecting your tooling is time wasted. I'm saying this having spent hours on YouTube trying to nail the "perfect" <a href="https://www.youtube.com/results?search_query=neovim+setup">Neovim setup</a> or <a href="https://www.youtube.com/results?search_query=obsidian">Obsidian setup</a> .</p><p>When tools have infinite customizability, our brain tricks us into thinking: surely if I configure this tool "the perfect way" I'll have superpowers. Our pursuit of perfect tooling will only lead to a dead-end. I doubt chefs spend this much time obsessing about their knives when they have a dish to make.</p><h2>The zen of avoiding the cool thing</h2><p>After completing my weekend proof of concept, I wanted to start building the actual product. I thought about using NextJS for this application but I think I have Javascript fatigue. I know building a t<em>hing</em> using Next is probably what the cool kids would do but in the words of one of my favorite artists:</p><blockquote><p>You can't be too cool, because then you'll just freeze to death.</p><p>- Tyler the Creator.</p></blockquote><p>I'm choosing not to do the cool thing. I'm building the application using <a href="https://laravel.com/">Laravel</a> (which is like Ruby on Rails) but for PHP. It gives me authentication, queues, workers, and sockets all out of the box. </p><p>In the JS ecosystem simple (yet core) parts of the application end up requiring entire companies. Like <a href="https://clerk.com/">Clerk</a> for authentication, <a href="https://pusher.com/">Pusher</a> for real time sockets, and <a href="https://trigger.dev/">Trigger</a> for queues and workers. </p><p>Maybe I'm jaded on the JS ecosystem but I know that each `npm install package` will inevitably come with issues. Either if it's needing to eject from the predefined happy path of these third party services, or their lack of documentation, or their cost, or their downtime.</p><blockquote><p> Find your dependencies and eliminate them.</p><p>- Excel team moto by Joel Spolsky.</p></blockquote><h2>Nginx on a Saturday morning</h2><p>Taking daily notes on development can paint a picture of overcoming difficult things. You inevitably come across a technical problem that <em>feels like work</em>. </p><p>For me, a couple Saturday mornings ago, I was trying to get an Nginx config wired the right way to work with SSL and CloudFare tunnels. What the words in the previous sentence mean doesn't really matter but what matters is that it was tough. But you put the work in, try different methods, and come out to the other side with some new scar tissue. The breakage of tissue is how muscle grows I'm told.</p><h2>Earning the right to work on things</h2><p>There's always a little rabbit telling Alice to go down a different hole. I'm Alice. The never-ending technical SAAS products is my rabbit hole. </p><p>One Tuesday evening I spent an hour looking at the perfect no-code Business Intelligence tool. Something that could give me insight into a product's user behavior. I have zero users. I barely have a product. Why was I wasting my time? I need to earn the right to work on certain things.</p><p>It's all distraction. Avoid it.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading thoughts &amp; experiments! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Yeah, Rust is low-key goated.]]></title><description><![CDATA[Thoughts on learning Rust by making a little project and using a little WASM.]]></description><link>https://blog.shahzeb.co/p/learn-rust</link><guid isPermaLink="false">https://blog.shahzeb.co/p/learn-rust</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Wed, 27 Mar 2024 21:53:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!O8Ri!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O8Ri!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O8Ri!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 424w, https://substackcdn.com/image/fetch/$s_!O8Ri!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 848w, https://substackcdn.com/image/fetch/$s_!O8Ri!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!O8Ri!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O8Ri!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg" width="736" height="414" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:414,&quot;width&quot;:736,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50185,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!O8Ri!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 424w, https://substackcdn.com/image/fetch/$s_!O8Ri!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 848w, https://substackcdn.com/image/fetch/$s_!O8Ri!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!O8Ri!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc64768a7-4193-4770-8eb7-55b8ab7a46ea_736x414.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Me at the function.</figcaption></figure></div><p>Every 3 months at the company All-Hands an intern asks the CTO if we can &#8220;rewrite our entire codebase in Rust?&#8221; And every time I wonder, what the heck is Rust.</p><p>I wanted to relate to my fellow interns so I decided to learn Rust. The following are thoughts from someone who writes way too much TypeScript and Python attempting to learn Rust over the past ~2 months. Strap in, it&#8217;s gonna be a real gathering of the minds.</p><p>If you just want to see what I built, and the code for it:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://redis.shahzeb.co/&quot;,&quot;text&quot;:&quot;View the app&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://redis.shahzeb.co/"><span>View the app</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/shahzeb1/redis-rs&quot;,&quot;text&quot;:&quot;View the code&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/shahzeb1/redis-rs"><span>View the code</span></a></p><h4>Foundations.</h4><p>Rust makes getting started extremely easy. Run the terminal command on <a href="https://rustup.rs/">rustup</a> and the Rust toolchain will be installed. Rust is a fairly mature language with a rich amount of high quality open-source educational material. I learnt most of the fundamentals using the <a href="https://blog.shahzeb.co/publish/post/142993099">Rust Programming Language book</a> and <a href="https://doc.rust-lang.org/rust-by-example/index.html">Rust By Examples</a> (both free online resources). </p><p>If you&#8217;re getting started, I recommend reading the first 4 chapters of the Programming Language book and then trying to build something yourself. When you come across an error or new concept, CTRL+F between the ebook book and the examples website.</p><h4>Why build a &#8220;Redis clone&#8221;?</h4><p>The only way to learn a language is to try and build something using it. Advanced concepts such as the &#8220;Rust borrow checker&#8221; aren&#8217;t going to make sense just by reading over some example code. </p><p>To me, <a href="https://redis.io/">Redis</a> is kind of the perfect tool to try and recreate. In the real world it&#8217;s used as a caching system / data store / queuing system. But at its core: you give Redis a string &#8594; it either gets or changes some data &#8594; it returns some data. Easy.</p><p>This core functionality of Redis is simple enough that it can be turned into a straightforward coding interview question. You can have a basic solution in &lt; 30 lines of JS. A bit of string parsing, mutate some objects, and return a string or number. Simple. But what if you want to add on complexity. How would you create a system that neatly handles 40+ commands? How would you handle creating a server that can execute these commands over HTTP? What about data persistence and importing / exporting data? Replicating data across nodes? What about making the same code run both on the CLI and on the web (spoiler alert)?</p><p>That&#8217;s why I kind of love Redis. It&#8217;s so simple yet you can choose to learn new things just by adding complexity. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Wpk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Wpk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 424w, https://substackcdn.com/image/fetch/$s_!8Wpk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 848w, https://substackcdn.com/image/fetch/$s_!8Wpk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 1272w, https://substackcdn.com/image/fetch/$s_!8Wpk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Wpk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png" width="646" height="461.42857142857144" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1040,&quot;width&quot;:1456,&quot;resizeWidth&quot;:646,&quot;bytes&quot;:636792,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8Wpk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 424w, https://substackcdn.com/image/fetch/$s_!8Wpk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 848w, https://substackcdn.com/image/fetch/$s_!8Wpk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 1272w, https://substackcdn.com/image/fetch/$s_!8Wpk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9008f546-38fa-484d-ac08-faad846ebdd1_2162x1544.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The final Redis CLI if you run it in your terminal.</figcaption></figure></div><p>So I decided to build a Redis CLI tool with the <strong>goal</strong> of learning:</p><ol><li><p>Fundamentals of Rust</p></li><li><p>How it handles basic user input and output</p></li><li><p>How to manipulate and pass around data</p></li><li><p>How Rust handles inheritance for different commands</p></li><li><p>Finally, can we get Rust to run on the web</p></li></ol><p>Here&#8217;s a list of things I learnt while working on my project, roughly in the order that I came across them.</p><h4>A compiler that tells you what&#8217;s wrong, and how to fix it.</h4><p>Like C++, Rust is a complied language. Which means there is a compiler involved. (Gathering of the minds, I told you). I&#8217;ve done a lot of C++ in my University days and I don&#8217;t miss seg faults, weird memory pointer issues (turns out it was actually a <em>skill issue</em>), super verbose typing, and using gdb at 1am. How much of that spills over into the Rust world?</p><p>Well, let&#8217;s start with the compiler. When you run `cargo run` it&#8217;ll build and run your code. This same command is when any build time issues will popup. And popup they will.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KQEt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KQEt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 424w, https://substackcdn.com/image/fetch/$s_!KQEt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 848w, https://substackcdn.com/image/fetch/$s_!KQEt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 1272w, https://substackcdn.com/image/fetch/$s_!KQEt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KQEt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png" width="1456" height="599" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:599,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:187806,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KQEt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 424w, https://substackcdn.com/image/fetch/$s_!KQEt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 848w, https://substackcdn.com/image/fetch/$s_!KQEt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 1272w, https://substackcdn.com/image/fetch/$s_!KQEt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6c0ad42-faf9-412a-ba2d-b42d10c3c112_2308x950.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Build error in Rust.</figcaption></figure></div><p>We&#8217;ll talk later about what this error actually means, but notice the fact that there is a &#8220;help&#8221; section where it tells you what you need to add (in the green text). This is a common trend with learning Rust: write a thing &#8594; compiler error &#8594; learn new concept &#8594; implement fix based on compiler error.</p><h4>It&#8217;s typed sensibly.</h4><p>The neat thing about Rust is that the language does a great job inferring the types. In fact, it does it much better than TypeScript. </p><p>Consider this TypeScript code (<a href="https://www.typescriptlang.org/play?ssl=2&amp;ssc=1&amp;pln=3&amp;pc=1#code/C4TwDgpgBAIghsOAVc0C8UCycwB4DOwATgJYB2A5gDRRkCuAtgEYREB8A3ALABQvAZnTIBjYCQD2ZKMKIQEEeIgDCkxOVYAKAJQAuWAmSooAb15RpkwlAAmBqBjIQA7lhzbuPc7OB0iU24geAL5AA">TS playground link</a>):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!u7na!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!u7na!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 424w, https://substackcdn.com/image/fetch/$s_!u7na!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 848w, https://substackcdn.com/image/fetch/$s_!u7na!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 1272w, https://substackcdn.com/image/fetch/$s_!u7na!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!u7na!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png" width="610" height="280.1744186046512" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:474,&quot;width&quot;:1032,&quot;resizeWidth&quot;:610,&quot;bytes&quot;:80461,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!u7na!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 424w, https://substackcdn.com/image/fetch/$s_!u7na!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 848w, https://substackcdn.com/image/fetch/$s_!u7na!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 1272w, https://substackcdn.com/image/fetch/$s_!u7na!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f31039a-50f9-4392-a242-7b171e3388f9_1032x474.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">TS can&#8217;t infer type based on parent return value.</figcaption></figure></div><p>Notice how we have a function returning a DataType. We have a map called `data` we return but `data` still has &#8220;any&#8221; as both the inferred key and value. It&#8217;s unable to infer that the `data` should be `Map&lt;string, number&gt;` based on the return type of the function. </p><p>Now, let&#8217;s see Rust in action (Git <a href="https://github.com/shahzeb1/redis-rs/blob/main/src/lib.rs#L48">codelink</a>): </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5PBL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5PBL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 424w, https://substackcdn.com/image/fetch/$s_!5PBL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 848w, https://substackcdn.com/image/fetch/$s_!5PBL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 1272w, https://substackcdn.com/image/fetch/$s_!5PBL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5PBL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png" width="630" height="197.64705882352942" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:320,&quot;width&quot;:1020,&quot;resizeWidth&quot;:630,&quot;bytes&quot;:63912,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5PBL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 424w, https://substackcdn.com/image/fetch/$s_!5PBL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 848w, https://substackcdn.com/image/fetch/$s_!5PBL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 1272w, https://substackcdn.com/image/fetch/$s_!5PBL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24bcc654-3f89-42b4-a35c-26af2a264d91_1020x320.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Rust can infer type based on parent return value.</figcaption></figure></div><p>Same exact function here but written in Rust. I didn&#8217;t actually add typing to `data` but it was correctly inferred `HashMap&lt;String, i64&gt;` based on the return type of the function. (The only reason you see it in gray is because the VSCode Rust plugin shows inferred types).</p><p>Amazing. This makes so much sense. This was a consistent theme while learning Rust: it made me realize TypeScript is the <a href="http://temu.com">Temu</a> typing system. Actually, that&#8217;s probably Python. We don&#8217;t need to talk about Python typing.</p><h4>Protect you from you.</h4><p>A major selling point of Rust is safety when it comes to memory access. C++ lets you pass around pointers and do whatever you want with them. Want to cast a Dog pointer into a Chair pointer? Cool, go for it. Turn a Train class object into a List of Dolphins? Sure. In C++ when you handoff a pointer in a function call, anything is possible. I think this is partially where the &#8220;let&#8217;s re-write it in Rust&#8221; meme comes from. Rust is much more strict about the way data is passed around and reassigned. It&#8217;s safer. </p><p>Part of what enables this memory safety is the <a href="https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html?highlight=borrow#references-and-borrowing">Rust borrow checker</a>. This is one system that can guarantee safety, but it comes at a cost: the learning curve. </p><p>Let&#8217;s see it in action. Let&#8217;s create a function called `execute` that pints out key and value.  </p><pre><code>fn execute(&amp;self, _: &amp;mut DataType) {
  let key = self.key;
  println!("{}", key)
}</code></pre><p>First we add key. Then we copy and paste the key line and change the &#8220;key&#8221; to value&#8221; for something like this:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0Ers!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0Ers!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 424w, https://substackcdn.com/image/fetch/$s_!0Ers!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 848w, https://substackcdn.com/image/fetch/$s_!0Ers!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 1272w, https://substackcdn.com/image/fetch/$s_!0Ers!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0Ers!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png" width="592" height="206.51162790697674" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:240,&quot;width&quot;:688,&quot;resizeWidth&quot;:592,&quot;bytes&quot;:46268,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0Ers!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 424w, https://substackcdn.com/image/fetch/$s_!0Ers!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 848w, https://substackcdn.com/image/fetch/$s_!0Ers!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 1272w, https://substackcdn.com/image/fetch/$s_!0Ers!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F777efe9f-db5c-4f87-8d8b-fb74fa6ca58b_688x240.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Wait, what&#8217;s this? We&#8217;re getting an error. I have an intentional typo where I forgot to change the second `self.key` to `self.value`. The type of bug speedy vim programmers make all the time. Because we&#8217;ve assigned `key` already, the borrow checker will guard against this kind of behavior. Neato!</p><h4>You&#8217;ve seen `structs` and `enums` before. But not like this.</h4><p>Instead of telling you, why don&#8217;t I show you. For our Redis clone, I want to handle 3 commands (I call actions): </p><ol><li><p>GET: get a value</p></li><li><p>SET: set a value</p></li><li><p>INCR : increase a numerical value by 1</p></li></ol><p>Since only one user action is possible at a time, let&#8217;s create an Action enum:</p><pre><code>pub enum Action {
    GetAction(Get),
    SetAction(Set),
    IncrAction(Incr),
}</code></pre><p>We can actually combine an enum and struct together in a way I haven&#8217;t seen in other languages. In our case, when we execute the GET command we input something like &#8220;GET coffee_shop_name&#8221;. Or we might execute &#8220;SET employee_count 12&#8221;. Each action has some associated data with it. Let&#8217;s use structs to define our 3 actions:</p><pre><code>pub struct Get(pub String);  // GET key

pub struct Incr(pub String); // INCR key

pub struct Set {             // SET key value
    pub key: String,
    pub value: String,
}</code></pre><p>Great, now we know the action the user is doing (like &#8220;SET&#8221;) and we know the value for that action (key and value). Now, how do we actually &#8220;do&#8221; stuff using this action. That&#8217;s where <a href="https://doc.rust-lang.org/book/ch10-02-traits.html?highlight=trait#traits-as-parameters">traits</a> and implementations come into play.</p><p>We want every Redis command to follow the same blueprint. In most languages we&#8217;d have an &#8220;Action&#8221; class and then each action (like SET or GET) would be a subclass of that. In Go we would have interfaces. In Rust we achieve this by having traits. Here&#8217;s the trait that defines the Redis action:</p><pre><code>pub trait ActionTrait {
    // Execute mutates the data
    fn execute(&amp;self, data: &amp;mut DataType);

    // Print the final response
    fn print(&amp;self, data: &amp;DataType);
} </code></pre><p>The trait requires the implementation to have two methods. </p><ol><li><p>An execute() method that gets passed a mutable data object. This is where SET will add to the data or INCR will update the numerical value by one.</p></li><li><p>A print() method that prints some result of the command. Some commands return &#8220;OK&#8221; other&#8217;s (such as GET) return an actual value. We could&#8217;ve had just one execute() method but I decided to split the &#8220;do stuff to data&#8221; and &#8220;return stuff to the screen&#8221; logic. It&#8217;ll help with the later WASM section.</p></li></ol><p>Now, we want to implement the blueprint for the SET command. Here&#8217;s how we do it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PxqE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PxqE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 424w, https://substackcdn.com/image/fetch/$s_!PxqE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 848w, https://substackcdn.com/image/fetch/$s_!PxqE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 1272w, https://substackcdn.com/image/fetch/$s_!PxqE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PxqE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png" width="1162" height="708" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:708,&quot;width&quot;:1162,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:160532,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PxqE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 424w, https://substackcdn.com/image/fetch/$s_!PxqE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 848w, https://substackcdn.com/image/fetch/$s_!PxqE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 1272w, https://substackcdn.com/image/fetch/$s_!PxqE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c00cc4e-22ee-4d5f-be6f-7cee4519794c_1162x708.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The implementation for the Set command.</figcaption></figure></div><p>Incredible stuff. First we&#8217;ll run execute() to add the key/value to our <em>data</em> data store, then we&#8217;ll run print() to print out &#8220;OK&#8221; (which is what Redis does when you SET a value). I&#8217;ve placed the files for the actions in their own dedicated <a href="https://github.com/shahzeb1/redis-rs/tree/main/src/actions">/actions folder</a>. Can you guess what the GET command&#8217;s execute() method does?</p><p></p><h4>The `match` statement:</h4><p>Now that we have a folder full of command action files, we need a way to run them. Let&#8217;s break it down:</p><ol><li><p>User passes in a string like &#8220;SET coffee_shop_name Sunrise Coffee&#8221;</p></li><li><p>We parse the user input string into an Action</p></li><li><p>Based on the Action, we execute and print the results.</p></li></ol><p>Here&#8217;s the code for these steps:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5qji!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5qji!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 424w, https://substackcdn.com/image/fetch/$s_!5qji!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 848w, https://substackcdn.com/image/fetch/$s_!5qji!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 1272w, https://substackcdn.com/image/fetch/$s_!5qji!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5qji!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png" width="1456" height="799" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:799,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:237863,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5qji!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 424w, https://substackcdn.com/image/fetch/$s_!5qji!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 848w, https://substackcdn.com/image/fetch/$s_!5qji!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 1272w, https://substackcdn.com/image/fetch/$s_!5qji!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ca59f88-de66-4db1-b0d2-99348ffb348e_1688x926.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Run the Redis action.</figcaption></figure></div><p>One thing Rust does really well is: correctly handling result. Quite often we write code where we either return a value or we return an error. Different languages handle this differently. Rust handles this using the <a href="https://doc.rust-lang.org/std/result/#result-and-option">Result</a> type. A Result consists of some data you return via `Ok(value)` or you return an error via `Err(E)`. Simple. </p><p>Now let&#8217;s walk through the above code:</p><ol><li><p>First we&#8217;re parsing the Action from the user string using a utility function I wrote called parse_action_from_user_string()</p><ol><li><p>Notice how the return type is a Result. Either the user&#8217;s input is a valid action, or we&#8217;ll return an error.</p></li></ol></li><li><p>Next we use a match statement. Just think of it as a switch statement on steroids (I&#8217;ll expand on this shortly). </p><ol><li><p>In the OK case we correctly parsed a valid action from the user provided string.</p><ol><li><p>Next we have another match statement. This one matches on the specific actions (GET or SET or INCR).</p><ol><li><p>Either run action.execute() or action.print() for GET, SET, INCR. Notice that there is no execute() called for GET because the GET command doesn&#8217;t actually change any data. It just prints a string.</p></li></ol></li></ol></li><li><p>For our root match statement we also have an Err arm for when the user provided string didn&#8217;t yield a valid action. Maybe the user input asked for an action we haven&#8217;t implemented yet or there was a typo in the string. Who knows.</p></li></ol></li></ol><p>Stellar! That&#8217;s basically the CLI implementation of the Redis CLI core. </p><p>I do want to mention that the `<a href="https://doc.rust-lang.org/book/ch18-01-all-the-places-for-patterns.html?highlight=match#match-arms">match</a>` expression operates in a much powerful way compared to a JS or Python switch statement. Let&#8217;s consider this TypeScript code that uses a switch statement (<a href="https://www.typescriptlang.org/play?#code/PTAEFEDsFcFsGdQEMBOBTZoBmakBdp1kATYtY0PAe1ACkkA3JAZQGMUBLABz1A8lAAVAJ5c0bTjwBQIUAHcAFh1YLQsJAGs0iDr1zwOaFJRoKkkYgBsMkJLHKh4aPIipZQrKpHh5zLgHRSMmAAQsKgZFhI0Ja85qBoMLB8iEkARkagaUhOxAA0jr4oePwA5si8AF5GVHnByBYJSCqgVDwcXinI8AalkA7x-Oxo9pC8aeFeaP5CSjrw9dBOWDHyComU66BMltAYHKlUvBywXFTFfoFSiXCgAMJUpznwACIc6KwlnQDeUqCgADlzngFHV-uAcngwaBmFRoCDoQB1bRQqQAXyCsjCDUgR3wZQaCSSrXaXgKwjhjmcmwwOz2AG56kN0KMXB4vCUYBgsChHpt8NskLs0AAuII3ZLMXwEeAPMiIX7-ADyAGlQABeUAAJgADDroSEkMQAEpoACOex8GtAABY9dCAKq2eEKc4car5P6gAAKSGErNNFve5GhADFzmkOKREtCgXhw9ALHUMfUAJqU9A4dCQVgYeISrLhJYEqBwAF2aYANSFeyCnm8vB8qE5pTeHy+Ak1DyePTbaE+HUg-ghPkZ9atrEI2bwUvwS2ts5lcu0-lVjPqpYQjmgXDOxWQrFzPQJxHwSD4AjSR1UxGDA68iB5fK0wnq1EFwoK5godIw75fVzjrwVAaACcAZMYmqLksy7wKuKpjg+wGgeBRgAJIWGgAAeC7SjBVDygA2gARKqxEALqIQ2hScJApSGia5qWrwUF4bKBHaIRdo6pRmJgJuiCsPEGQRBwWBZokvB4KI2hfjRBLSWIXSeLAsBeIEsgOgYdGYD4tHlEJAjqFofB6DkhjGO+ZBpNApQFBkQlLH+6z1L+FSgCgiYlPYERUNooC4rw6BBkQFLQCYoCWFQIGgDuNIBahKBXAWADiFa+sQGFcPCoCKqADpcNaxEOt6xHQi8VByJ2oDES8SqIgCZVegAMmgWAsTVzXgKGghNf8xocKUCgdcRxpoSlAASvXJnxoBoe4YXyH4EXoMQ0C5vF6SZG4rRpAAVv2bL8KAYUoPU9BMBI3BBV5JxoOSlKGR46D4Hm7LURKVyyAAgu9VoSgA5IgbkHB5aBcJYzQOBMQgyVdPARIQZRvig5jwFwHCQx2rQLXCxieGQBT8D4uAUDtGQElFIEODurkcOe8RUPth3uZ5Yx3YBSFErcACycJON994CHlfNORVVXQqLTgFUq8IGITXpS2gBUYfL93onWXNmBY1hK4L2OagAFM0HYiqAetCwAlBqAB8uVevAci6C0xtW-b-z-EJTjm-zaD64O-hK+LkBih7HvjlQ1j+FFpSG8RSugMHxGW4yYf-GkL0aKnoAYmi66yPNJ2UlTGjuSCf6o94GPWBQF0sOw10PeFT1OGg9SunI8XXpkEqINhBxxK4zOfIg37YImQvwHUsgd2gDCZBb2Og4FNLoF9YCCHMXRCvANB4J53LnPFKj9qXSClEgxO8IvAdB5VkBMt4UbORgjvO6oTZ4CMkkXmroDa1YNAN91KzQEh4eIxAaBqSICCeIIIDhN3AQIF6FBoH7AEOXeoIgxDw14AAq8IExQgHbngPAXB4AihAHIah-hFLaAbjwSGdF-DnFKMASBrB4DAHwdFDQwBe7+GGrASwUggA">playground</a>):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NTaA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NTaA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 424w, https://substackcdn.com/image/fetch/$s_!NTaA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 848w, https://substackcdn.com/image/fetch/$s_!NTaA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 1272w, https://substackcdn.com/image/fetch/$s_!NTaA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NTaA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png" width="604" height="352.987012987013" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:540,&quot;width&quot;:924,&quot;resizeWidth&quot;:604,&quot;bytes&quot;:87520,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NTaA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 424w, https://substackcdn.com/image/fetch/$s_!NTaA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 848w, https://substackcdn.com/image/fetch/$s_!NTaA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 1272w, https://substackcdn.com/image/fetch/$s_!NTaA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36b9bf3b-9b00-4a52-a273-a808ca6a8648_924x540.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">TypeScript === Temu Typing.</figcaption></figure></div><p>Notice how the switch statement only considers one case (the MouseDown case). We completely disregarded MouseUpOutside and MouseUpInside. TypeScript doesn&#8217;t have an issue with this.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YXmY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YXmY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 424w, https://substackcdn.com/image/fetch/$s_!YXmY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 848w, https://substackcdn.com/image/fetch/$s_!YXmY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 1272w, https://substackcdn.com/image/fetch/$s_!YXmY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YXmY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png" width="1456" height="811" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:811,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:395918,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YXmY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 424w, https://substackcdn.com/image/fetch/$s_!YXmY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 848w, https://substackcdn.com/image/fetch/$s_!YXmY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 1272w, https://substackcdn.com/image/fetch/$s_!YXmY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab21e3c6-51d3-448c-a717-da1364315711_2058x1146.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I deleted the &#8220;Incr&#8221; arm in the match.</figcaption></figure></div><p>With `match`, every case of the enum needs to be accounted for. Think about how great that is: if I want to add a new command, I add it to the <a href="https://github.com/shahzeb1/redis-rs/blob/main/src/actions.rs#L24">Action enum</a> and at build time the Rust compiler will tell me that there are forks in the code I have to update. </p><p>Also, notice how the Result type is being matched against at the root. This is like being able to switch on errors. In other languages we&#8217;d need to have some kind of a try/catch mechanism. Oh yeah, and good luck properly propagating the caught error to your observability tool like Sentry. Also guess what happens if I delete the Err arm of the root match statement? </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RES9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RES9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 424w, https://substackcdn.com/image/fetch/$s_!RES9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 848w, https://substackcdn.com/image/fetch/$s_!RES9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 1272w, https://substackcdn.com/image/fetch/$s_!RES9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RES9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png" width="1456" height="939" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:939,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:241497,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RES9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 424w, https://substackcdn.com/image/fetch/$s_!RES9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 848w, https://substackcdn.com/image/fetch/$s_!RES9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 1272w, https://substackcdn.com/image/fetch/$s_!RES9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6bc8d52-3e7b-4f5a-84ac-e4118d17d4e5_1522x982.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Build error by deleting the Err arm of match.</figcaption></figure></div><p>That&#8217;s right, a compiler error. This means that match combined with Result forces you to always consider the path with errors. Every JavaScript developer is shrieking.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IVdf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IVdf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 424w, https://substackcdn.com/image/fetch/$s_!IVdf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 848w, https://substackcdn.com/image/fetch/$s_!IVdf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 1272w, https://substackcdn.com/image/fetch/$s_!IVdf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IVdf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png" width="540" height="322.9906542056075" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/51b93264-0113-4244-a73e-37243491103d_1177x704.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:704,&quot;width&quot;:1177,&quot;resizeWidth&quot;:540,&quot;bytes&quot;:245621,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IVdf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 424w, https://substackcdn.com/image/fetch/$s_!IVdf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 848w, https://substackcdn.com/image/fetch/$s_!IVdf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 1272w, https://substackcdn.com/image/fetch/$s_!IVdf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51b93264-0113-4244-a73e-37243491103d_1177x704.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">You&#8217;ll get used to it.</figcaption></figure></div><p></p><h4>Compiling executables for the web?</h4><p>Sounds like a fever dream.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jnl2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jnl2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 424w, https://substackcdn.com/image/fetch/$s_!Jnl2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 848w, https://substackcdn.com/image/fetch/$s_!Jnl2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 1272w, https://substackcdn.com/image/fetch/$s_!Jnl2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jnl2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png" width="1456" height="928" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:928,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:799607,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jnl2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 424w, https://substackcdn.com/image/fetch/$s_!Jnl2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 848w, https://substackcdn.com/image/fetch/$s_!Jnl2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 1272w, https://substackcdn.com/image/fetch/$s_!Jnl2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaa2cf30-d4d7-4889-a988-ce979136e544_2784x1774.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The web application on redis.shahzeb.co which is powered by web-assembly (WASM).</figcaption></figure></div><p>Web-assembly (or WASM) could probably be it&#8217;s own blog post (wink wink). The one thing I&#8217;ll say is that the WASM + Rust toolchain is really solid. I used <a href="https://rustwasm.github.io/wasm-pack/installer/">wasm-pack</a> to build the WASM binary artifacts. Copied them over to my frontend&#8217;s <a href="https://github.com/shahzeb1/redis-www/tree/main/src/pkg">src/pkg folder</a> and used it in my React component right <a href="https://github.com/shahzeb1/redis-www/blob/main/src/components/redis-container.tsx#L19">here</a>:</p><pre><code>// Import the artifacts from wasm-pack:
import * as wasmPkg from "../pkg";

// Init the wasm class:
const wasm = useMemo(() =&gt; new wasmPkg.WasmRunnerContainer(), []);

// Run the run method on my class:
const output = wasm.run("SET coffe_shop_name Sunrise Coffee");</code></pre><p>This is powerful stuff.  We&#8217;re now taking user input on a website &#8594; passing it to a compiled module written in Rust &#8594; returning a string we show again on a <a href="https://redis.shahzeb.co/">web app</a>. </p><h4>Some parting thoughts.</h4><p>So, should we create a JIRA ticket to re-write the entire company in Rust? Well there&#8217;s probably some wisdom in the <a href="https://www.propelauth.com/post/i-love-building-a-startup-in-rust-i-wouldnt-pick-it-again">I love building a startup in Rust. I wouldn&#8217;t pick it again</a> article. </p><p>I think Rust is really impressive. It&#8217;s both challenging and fulfilling to learn. The ecosystem and developer experience feels top-of-class. It has shown me the light of a brilliantly engineered typing system. But it comes at the cost of moving slow and a steep learning curve. If you are bootstrapping your own startup or work at a &#8220;intense and fast paced&#8221; company where changes should&#8217;ve gone live yesterday, then stick with more forgiving languages. Tradeoffs to consider. Ultimately it&#8217;s your call. I&#8217;m just a boy with a Substack.</p><p>Also, <a href="https://www.youtube.com/@jonhoo/videos">Jon Gjengset&#8217;s YouTube channel</a> and his <a href="https://www.amazon.com/Rust-Rustaceans-Programming-Experienced-Developers-ebook/dp/B0957SWKBS">book</a> are an incredible resource and part of the reason I wanted to learn Rust in the first place. He has the best &#8220;advanced&#8221; programming YouTube content out there IMO.</p><p>There are many things such as <a href="https://doc.rust-lang.org/book/ch19-06-macros.html?highlight=macros#macros">macros</a>, fearless <a href="https://doc.rust-lang.org/book/ch16-00-concurrency.html?highlight=fearless#fearless-concurrency">concurrency</a>, the <a href="https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html?highlight=module#grouping-related-code-in-modules">module system</a>, and advanced types such as <a href="https://doc.rust-lang.org/book/ch15-01-box.html?highlight=box#enabling-recursive-types-with-boxes">Box</a> and <a href="https://doc.rust-lang.org/book/ch15-06-reference-cycles.html?highlight=RefCell#preventing-reference-cycles-turning-an-rc-into-a-weak">RefCell</a> which I simply didn&#8217;t get into. Maybe next time &#129335;&#127999;.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.shahzeb.co/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/p/learn-rust?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.shahzeb.co/p/learn-rust?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p>Edit: if anyone has a &#8220;I &lt;3 the Rust match Statement&#8221; t-shirt please get in touch.</p>]]></content:encoded></item><item><title><![CDATA[MiniGPT: Building a functional ChatGPT clone]]></title><description><![CDATA[In as few lines of code, using Llama 2, Cloudflare AI workers, and our beloved deployment tool Vercel.]]></description><link>https://blog.shahzeb.co/p/building-chatgpt-clone</link><guid isPermaLink="false">https://blog.shahzeb.co/p/building-chatgpt-clone</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Mon, 23 Oct 2023 21:26:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qmP7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qmP7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 424w, https://substackcdn.com/image/fetch/$s_!qmP7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 848w, https://substackcdn.com/image/fetch/$s_!qmP7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 1272w, https://substackcdn.com/image/fetch/$s_!qmP7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qmP7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png" width="1456" height="1001" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/86d43547-0048-4182-a435-417ff926dac7_2152x1480.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1001,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:616645,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qmP7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 424w, https://substackcdn.com/image/fetch/$s_!qmP7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 848w, https://substackcdn.com/image/fetch/$s_!qmP7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 1272w, https://substackcdn.com/image/fetch/$s_!qmP7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86d43547-0048-4182-a435-417ff926dac7_2152x1480.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">MiniGPT in action.</figcaption></figure></div><p></p><p><em>This post is the first post in the series that goes in depth about building <a href="http://gpt.shahzeb.co">MiniGPT</a>.</em></p><p>The other day I read a blogpost from Cloudflare titled &#8220;<a href="https://blog.cloudflare.com/writing-poems-using-llama-2-on-workers-ai/">Writing poems using LLama 2 on Workers AI</a>&#8221;. The blogpost shows how using <a href="https://blog.cloudflare.com/workers-ai/">workers AI</a> (Cloudflare&#8217;s serverless lambda functions) we can very easily spin up endpoints that interact with LLMs (large language models). The blogpost demonstrates how in roughly 9 lines of Javascript you can send a prompt to an AI model.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Shahzeb&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The magic happens here:</p><pre><code>import { Ai } from "@cloudflare/ai";
...
const response = await ai.run("@cf/meta/llama-2-7b-chat-int8", body);</code></pre><p>All the complexity is abstracted away in the &#8220;ai&#8221; package. </p><p>This got me thinking, how hard would it be to make a little ChatGPT application that uses Llama?</p><h2>A weekend side project</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eqLf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eqLf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 424w, https://substackcdn.com/image/fetch/$s_!eqLf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 848w, https://substackcdn.com/image/fetch/$s_!eqLf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 1272w, https://substackcdn.com/image/fetch/$s_!eqLf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eqLf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png" width="1456" height="1068" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1068,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:577936,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eqLf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 424w, https://substackcdn.com/image/fetch/$s_!eqLf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 848w, https://substackcdn.com/image/fetch/$s_!eqLf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 1272w, https://substackcdn.com/image/fetch/$s_!eqLf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68cd8981-4f8a-4bb4-883e-d4b19f00a544_2088x1532.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Even if your life is falling apart, you can still make Notion docs to track it.</figcaption></figure></div><p>I like to use Notion to track my little side projects. The only way to complete a side project is by tackling the hardest part first. It&#8217;s easy to get distracted by the things you&#8217;re already good at. If you can get over the initial challenging part, it&#8217;ll give you enough velocity to get to the finish line. In this case, I was relatively unfamiliar with Cloudflare workers and interacting with Llama, so that&#8217;s where I decided to start.</p><h2>Using serverless AI functions on the edge</h2><p>So many techy buzz words! Let me explain:</p><ol><li><p>We&#8217;re gonna use the <code>@cloudflare/ai</code> package to run our <strong>AI function </strong></p></li><li><p>These AI functions (called workers) are distributed to the Cloudflare <strong>edge</strong> network. It&#8217;s impressive how quickly I hit save on the function was available on prod.</p></li></ol><p>&#9888;&#65039; When launching a new worker AI function, Cloudflare makes it quite clear that this is a beta feature not intended for production traffic. We&#8217;re gonna scroll past that warning so fast, it&#8217;s like it was never even there.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eXKT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eXKT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 424w, https://substackcdn.com/image/fetch/$s_!eXKT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 848w, https://substackcdn.com/image/fetch/$s_!eXKT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 1272w, https://substackcdn.com/image/fetch/$s_!eXKT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eXKT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png" width="1456" height="965" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:965,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:730230,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eXKT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 424w, https://substackcdn.com/image/fetch/$s_!eXKT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 848w, https://substackcdn.com/image/fetch/$s_!eXKT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 1272w, https://substackcdn.com/image/fetch/$s_!eXKT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb999766b-9da6-40d4-99e7-580a2200d2cc_2232x1480.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cloudflare worker quick edit.</figcaption></figure></div><p>After going through the Cloudflare worker creation wizard, you have the ability to &#8220;Quick edit&#8221; the code right in the browser. No need to clone any <code>git</code> repos. The Cloudflare worker editor has a built in textarea (powered by <a href="https://microsoft.github.io/monaco-editor/">Monoco</a> which is basically VSCode for the web) and has a mini &#8220;Postman&#8221; area where you can make web requests to your function. Super easy to use.</p><p>Here&#8217;s the code for the function that uses Meta&#8217;s <code>llama-2-7b-chat-int8</code> model.</p><pre><code>import { Ai } from './vendor/@cloudflare/ai.js'
import { handleRequest } from './cors.js';

async function miniLLM(request, env) {
  const body = await request.json();
  const messages = body.messages;
  const ai = new Ai(env.AI);
  const response = await ai.run("@cf/meta/llama-2-7b-chat-int8", {
    messages
  });
  return response;
}

export default {
  async fetch(request, env){
      return handleRequest(request, env, miniLLM);
  },
};</code></pre><p>The shape of the incoming <code>message POST </code>body is  a conversation between the user and the system:</p><pre><code>[
  {
    "role": "user",
    "content": "What is climate change, but tell me in a funny way?"
  },
  { "role": "system", "content": "Climate change is not lit, ..." }
]</code></pre><p>This is how most LLMs describe their back-and-forth conversations with the users.</p><p>Even though I was able to test out my function in the Cloudflare editor, I was unable to make <code>fetch()</code> requests to it from my local frontend. It was a classic CORS issue. Here&#8217;s the code that&#8217;ll give you the ability to whitelist specific domains to your worker function:</p><pre><code>const corsHeaders = {
    'Access-Control-Allow-Headers': '*', 
    'Access-Control-Allow-Methods': 'POST',
    'Access-Control-Allow-Origin': 'https://gpt.shahzeb.co',
  };
  
export async function handleRequest(request, env, cb) {
    if (request.method === "OPTIONS") {
      return new Response("OK", {
        headers: corsHeaders
      });
    } else if (request.method === 'POST') {
      const res = await cb(request, env);
      return new Response(JSON.stringify(res), {
        headers: {
          'Content-type': 'application/json',
          ...corsHeaders
        }
      });
    } else {
      return new Response("Method not allowed", {
        status: 405,
        headers: corsHeaders
      });
    }
  } </code></pre><p>Not including the CORS helper function, we can now make <code>POST</code> requests to an endpoint which is globally distributed. All in exactly 18 lines of code.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7OCi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7OCi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 424w, https://substackcdn.com/image/fetch/$s_!7OCi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 848w, https://substackcdn.com/image/fetch/$s_!7OCi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 1272w, https://substackcdn.com/image/fetch/$s_!7OCi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7OCi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png" width="1456" height="1079" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1079,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:233798,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7OCi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 424w, https://substackcdn.com/image/fetch/$s_!7OCi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 848w, https://substackcdn.com/image/fetch/$s_!7OCi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 1272w, https://substackcdn.com/image/fetch/$s_!7OCi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc09f5ec-6a3e-49d8-ba64-a10da37fa2ce_1706x1264.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cloudflare worker dashboard for the llama worker.</figcaption></figure></div><p></p><h2>Prompt Engineering 101</h2><p>I&#8217;ve been trying to burn down my <a href="https://letterboxd.com/">Letterboxd</a> watchlist. One movie that&#8217;s been on my list forever is the 2005 movie <em>Pride and Prejudice</em> starring Tom Wambsgans from the hit HBO drama series <em>Succession</em>. It&#8217;s a solid movie with some really pretty writing (shout out Jane Austen). This got me thinking; can I force the LLM to respond to me as a specific author?</p><p>Welcome to a quick prompt engineering crash course. Before we make a request to our AI function, we are going to modify the <code>message</code> we send to the backend with some additional text.</p><p>On the UI when a user selects Jane Austen as the desired voice, we change the <code>prompt</code> before making the request. If the user prompts &#8220;What is the best drink?&#8221; that then becomes: &#8220;In the style of Jane Austen, answer the following prompt: What is the best drink?&#8221; It&#8217;s really that simple. Functionally speaking, typing in that pre-prompt into the prompt textarea and selecting Jane Austen from the dropdown will get the same result. </p><p>Here&#8217;s a snippet from the frontend for of how we convert the prompt voices:</p><pre><code>export type voices = ("none" | "brevity") | authors;
export type authors =
  | "Jane Austen"
  | "Ernest Hemingway"
  | "John Steinbeck"
  | "Mark Twain";

export const PROMPT_VOICE = (prompt: string, voice: voices): string =&gt; {
  switch (voice) {
    case "brevity":
      return `Within 4 sentences or less, answer the following prompt: ${prompt}`;
    case "Jane Austen":
      return `In the style of Jane Austen, answer the following prompt: ${prompt}`;
    ...
    default:
      return prompt;
  }
};</code></pre><p>I added the &#8220;Brevity&#8221; option as a voice because the shorter response means the AI runs faster and is less likely to end on an open sentence.</p><p>In our client, where we make the request to our backend, we use this <code>PROMPT_VOICE </code>function to reshape the <code>prompt</code> in our <code>userInput:</code></p><pre><code>const userInput: Response = {
      content: PROMPT_VOICE(prompt, promptVoice),
      role: "user",
    };
const req = [...prevResponses, userInput];
const res = await promptRequest({ messages: req }); // does the fetch()</code></pre><p>At this point we have a functional deployed backend we can have a conversation with.</p><h2>I hate to leave you on a cliffhanger&#8230;</h2><p>&#8230;but this post is getting very long. Substack is yelling at me that this post will not fit in an email. Whole time I&#8217;m thinking, <a href="https://twitter.com/paddysroyco/status/1716098485345189992">who reads email</a>. </p><p>Hopefully you do because if you subscribe (it&#8217;s free, just put in your email bellow) I&#8217;ll be sharing two new posts in this series:</p><ol><li><p>The frontend for MiniGPT</p><ol><li><p>Tools used to build it</p></li><li><p>Deploy it</p></li><li><p>How to debug the most pain-in-the-ass mobile responsive UI bug with a CSS hack</p></li><li><p>&#8252;&#65039; Link to the code &#8252;&#65039;</p></li></ol></li><li><p>The best side project database I&#8217;ve found</p><ol><li><p>I&#8217;m using it to track the total number of prompts so far on the homepage</p></li><li><p>Avoid AWS at all costs</p></li><li><p>Spend like $5 on it</p></li></ol></li></ol><p>As always, thanks.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Shahzeb&#8217;s Substack! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Moving my blog from Svbtle to Substack]]></title><description><![CDATA[Let's blame SSL certificates.]]></description><link>https://blog.shahzeb.co/p/moving-from-svbtle-to-substack</link><guid isPermaLink="false">https://blog.shahzeb.co/p/moving-from-svbtle-to-substack</guid><dc:creator><![CDATA[Shahzeb]]></dc:creator><pubDate>Mon, 23 Oct 2023 18:09:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!h_Dg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h_Dg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h_Dg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 424w, https://substackcdn.com/image/fetch/$s_!h_Dg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 848w, https://substackcdn.com/image/fetch/$s_!h_Dg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 1272w, https://substackcdn.com/image/fetch/$s_!h_Dg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h_Dg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png" width="1456" height="1069" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1069,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;privacy-error.png&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="privacy-error.png" title="privacy-error.png" srcset="https://substackcdn.com/image/fetch/$s_!h_Dg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 424w, https://substackcdn.com/image/fetch/$s_!h_Dg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 848w, https://substackcdn.com/image/fetch/$s_!h_Dg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 1272w, https://substackcdn.com/image/fetch/$s_!h_Dg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5c84ab7-69e4-459d-b3ed-46e024c87d33_1600x1175.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I was an early user on <a href="https://svbtle.com/">Svbtle</a> back when I saw a &#8220;Show HN&#8221; thread about it on HackerNews.</p><p>I loved the minimal design. I loved how it works really well on mobile. I dig the draft preview URLs. I think the composer makes it super easy to write without distractions. I&#8217;ve had no complaints about it for the past ~4 years. It does what every blogging platform should do, without any-frills.</p><p>The main reason I&#8217;m moving on is: SSL. Chrome would show a privacy error when users visited my custom blog domain because Svbtle doesn&#8217;t use custom domain SSL certs. Custom domain certs have been a private beta feature for more than a year now. I&#8217;ve written to the Svbtle team asking them to give me access, but have gotten no response from them. On Chrome (and any browser using a &#8220;Force HTTPS&#8221; extension) this makes my blog totally unusable. Having custom domain certs for paying customers should have been treated as an urgent high priority item. It should have been on by default for all users.</p><p>Anyways, I&#8217;m sad to move on from Svbtle, but excited for a fresh start on a new platform. I&#8217;ll be writing about random AI / web things I&#8217;m learning and building. You might get a post or two a month. Feel free to subscribe (it&#8217;s free and all the cool kids are doing it).</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.shahzeb.co/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.shahzeb.co/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item></channel></rss>