<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Welcome on Ishan Das Sharma</title>
        <link>https://ishan.page/</link>
        <description>Recent content in Welcome on Ishan Das Sharma</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Wed, 14 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ishan.page/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>How to Generate Presigned URLs for R2 When Using Cloudflare Workers (And Make Sure They Actually Work)</title>
        <link>https://ishan.page/blog/cloudflare-r2-workers-presigned/</link>
        <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/cloudflare-r2-workers-presigned/</guid>
        <description>&lt;p&gt;So you want to let users upload files directly to Cloudflare R2 from their browser? Great idea! Presigned URLs are the way to do it.&lt;/p&gt;
&lt;p&gt;You follow the documentation, you generate a presigned URL, and&amp;hellip; &lt;strong&gt;403 Forbidden&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let me show you how to fix all of this.&lt;/p&gt;
&lt;h2 id=&#34;step-1-use-the-right-library&#34;&gt;Step 1: Use the Right Library&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Don&amp;rsquo;t use&lt;/strong&gt; the official AWS SDK. It doesn&amp;rsquo;t work in Cloudflare Workers because it needs Node.js APIs that Workers don&amp;rsquo;t have.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do use&lt;/strong&gt; &lt;code&gt;aws4fetch&lt;/code&gt; - it&amp;rsquo;s built specifically for Workers and uses the Web APIs that Workers actually support.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install aws4fetch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-2-generate-the-presigned-url&#34;&gt;Step 2: Generate the Presigned URL&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the code that actually works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AwsClient&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;aws4fetch&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;           &lt;span class=&#34;c1&#34;&gt;// e.g., &amp;#34;uploads/myfile.mp3&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;nx&#34;&gt;expiresIn&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;number&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;// seconds, e.g., 3600 = 1 hour
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// Create the client
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AwsClient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;accessKeyId&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;env.R2_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;secretAccessKey&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;env.R2_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;s3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;auto&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// R2 uses &amp;#39;auto&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// Build the URL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;r2Url&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`https://&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;R2_ACCOUNT_ID&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;.r2.cloudflarestorage.com`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;objectUrl&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r2Url&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;/my-bucket/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;?X-Amz-Expires=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;expiresIn&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// Sign it - this is the magic part
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;signedRequest&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sign&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;objectUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;PUT&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;// DON&amp;#39;T include Content-Type here - more on this below
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;signQuery&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;true&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;signedRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-3-the-content-type-trap-this-one-got-me&#34;&gt;Step 3: The Content-Type Trap (This One Got Me)&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s something that drove me crazy debugging: if you include &lt;code&gt;Content-Type&lt;/code&gt; in the signed headers, the browser upload will fail even though curl works fine.&lt;/p&gt;
&lt;p&gt;Why? Because when you use &lt;code&gt;signQuery: true&lt;/code&gt; with aws4fetch, it only signs the &lt;code&gt;host&lt;/code&gt; header. If you try to send other headers from the browser, R2 sees unsigned headers and rejects the request.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t sign Content-Type. Don&amp;rsquo;t send it manually from the browser either. Just let the browser handle it automatically:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// In your frontend code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;presignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Don&amp;#39;t do this: xhr.setRequestHeader(&amp;#34;Content-Type&amp;#34;, file.type);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// Just send the file - browser adds headers automatically
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;R2 will still store the file with the correct content type. It just won&amp;rsquo;t validate it against the signature.&lt;/p&gt;
&lt;h2 id=&#34;step-4-configure-cors-the-most-important-part&#34;&gt;Step 4: Configure CORS (The Most Important Part)&lt;/h2&gt;
&lt;p&gt;This is probably why your upload isn&amp;rsquo;t working. Even with a perfect presigned URL, &lt;strong&gt;R2 blocks browser requests unless you configure CORS&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You need to tell R2 &amp;ldquo;yes, browsers can upload files here.&amp;rdquo; Here&amp;rsquo;s how:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Create a CORS policy file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat &amp;gt; cors-policy.json &lt;span class=&#34;s&#34;&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;  &amp;#34;CORSRules&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;      &amp;#34;AllowedOrigins&amp;#34;: [&amp;#34;https://your-domain.com&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;      &amp;#34;AllowedMethods&amp;#34;: [&amp;#34;GET&amp;#34;, &amp;#34;PUT&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;      &amp;#34;AllowedHeaders&amp;#34;: [&amp;#34;*&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;      &amp;#34;ExposeHeaders&amp;#34;: [&amp;#34;ETag&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;      &amp;#34;MaxAgeSeconds&amp;#34;: 3600
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Apply it to your bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aws s3api put-bucket-cors &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  --bucket your-bucket-name &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  --cors-configuration file://cors-policy.json &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  --endpoint-url &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R2_ACCOUNT_ID&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.r2.cloudflarestorage.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;During development, you can use &lt;code&gt;&amp;quot;AllowedOrigins&amp;quot;: [&amp;quot;*&amp;quot;]&lt;/code&gt; to allow all origins. Just remember to lock it down in production!&lt;/p&gt;
&lt;h2 id=&#34;step-5-set-up-your-environment-variables&#34;&gt;Step 5: Set Up Your Environment Variables&lt;/h2&gt;
&lt;p&gt;You need these secrets in your Cloudflare Worker:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Get these from Cloudflare Dashboard → R2 → Manage R2 API Tokens&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx wrangler secret put R2_ACCESS_KEY_ID
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx wrangler secret put R2_SECRET_ACCESS_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx wrangler secret put R2_ACCOUNT_ID
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Your Worker needs all three to generate presigned URLs.&lt;/p&gt;
&lt;h2 id=&#34;the-complete-flow&#34;&gt;The Complete Flow&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s how it all works together:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Backend (Cloudflare Worker):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Generate presigned URL when requested
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`uploads/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;crypto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;randomUUID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;.mp3`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;presignedUrl&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;JSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stringify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;uploadUrl&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;presignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;publicUrl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`https://your-domain.com/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Frontend (Browser):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 1. Get presigned URL from your API
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;/api/generate-upload-url&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;uploadUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;publicUrl&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 2. Upload file directly to R2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uploadUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;PUT&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 3. File is now in R2! Use publicUrl to reference it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;File uploaded:&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;publicUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;testing-your-implementation&#34;&gt;Testing Your Implementation&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a quick test to see if everything works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// In browser console on your site
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;testFile&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Blob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;test content&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Get presigned URL from your API
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;/api/generate-upload-url&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;uploadUrl&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Try to upload
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;uploadResponse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uploadUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;PUT&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;testFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Upload result:&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;uploadResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Should see: 200 (success!)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you get 200, congrats! If not, check the browser console for CORS errors or network tab for the actual error response.&lt;/p&gt;
&lt;h2 id=&#34;the-full-picture&#34;&gt;The Full Picture&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s what I ended up with in my production app:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;worker/r2-utils.ts:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AwsClient&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;aws4fetch&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;generateR2PresignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;contentType&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;expiresIn&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;credentials&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;R2_ACCESS_KEY_ID&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;R2_SECRET_ACCESS_KEY&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;R2_ACCOUNT_ID&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;R2_BUCKET?&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;AwsClient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;accessKeyId&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;credentials.R2_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;secretAccessKey&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;credentials.R2_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;s3&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;auto&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;bucketName&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;credentials&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;R2_BUCKET&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;my-bucket&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;r2Url&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`https://&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;credentials&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;R2_ACCOUNT_ID&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;.r2.cloudflarestorage.com`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;objectUrl&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r2Url&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bucketName&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;?X-Amz-Expires=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;expiresIn&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;signedRequest&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sign&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;objectUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;PUT&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;signQuery&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;true&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;signedRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Frontend upload component:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;uploadFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;File&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// 1. Get presigned URL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;presignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;publicUrl&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;generatePresignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;filename&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;file.name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;contentType&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;file.type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// 2. Upload to R2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;presignedUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// Track progress
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;upload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onprogress&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lengthComputable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;percent&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loaded&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Upload progress: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;percent&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;%`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// Send the file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// 3. Wait for completion
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;reject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onload&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;reject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;xhr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onerror&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;reject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;publicUrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Getting presigned URLs working with Cloudflare Workers was way harder than it should have been. The AWS documentation doesn&amp;rsquo;t help because Workers aren&amp;rsquo;t Node.js. Most examples online use the AWS SDK which doesn&amp;rsquo;t work. Even Cloudflare themselves doesn&amp;rsquo;t have a document anywhere (that I could find at least!) telling us that we can&amp;rsquo;t use the AWS SDK (or documenting these gotchas).&lt;/p&gt;
&lt;p&gt;But once you know the tricks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;aws4fetch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t sign Content-Type&lt;/li&gt;
&lt;li&gt;Configure CORS&lt;/li&gt;
&lt;li&gt;Let the browser handle headers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;hellip;it actually works great! And your users can upload files directly to R2 without killing your Worker.&lt;/p&gt;
&lt;p&gt;Hope this saves you the hours of debugging I went through. If you&amp;rsquo;re still stuck, the issue is probably CORS. It&amp;rsquo;s almost always CORS.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>What I Learned Using Neon Postgres for a Week of Live Traffic</title>
        <link>https://ishan.page/blog/dbms-neon/</link>
        <pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/dbms-neon/</guid>
        <description>&lt;p&gt;I recently built a &lt;a class=&#34;link&#34; href=&#34;https://oppe.dev&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SQL practice platform&lt;/a&gt; for my DBMS course at &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/jeeification&#34; &gt;IITM BS Degree&lt;/a&gt;. About 50-100 students were hitting it simultaneously during peak exam prep. I chose Neon as the backend database, mostly because I was curious about their serverless Postgres offering. Here&amp;rsquo;s what I learned after a week of actual traffic.&lt;/p&gt;
&lt;p&gt;Let me be clear about what this actually tested: student queries don&amp;rsquo;t hit Neon at all. Those run in WASM on the client side (which I&amp;rsquo;ll write about in Part 2 because that setup was &lt;em&gt;wild&lt;/em&gt;). Neon&amp;rsquo;s job was simple: serve metadata like problem sets, some aggregate stats, and admin operations. This is basically the lightest possible database workload - maybe 2-3 queries per page load, all reads except when I manually added new problems through TablePlus.&lt;/p&gt;
&lt;p&gt;Strictly speaking, this website didn&amp;rsquo;t even need a database since it could have been entirely pre-rendered. But this project is experimental for me. I used Lovable to scaffold the UI, tried TRPC for the first time, used Bun instead of my usual Python stack, and generally did things quite differently from my usual approach. I&amp;rsquo;ll detail those decisions in future posts. For now, Neon&amp;rsquo;s role was serving the application&amp;rsquo;s metadata and admin operations.&lt;/p&gt;
&lt;p&gt;So this isn&amp;rsquo;t &amp;ldquo;I ran a high-traffic production database on Neon.&amp;rdquo; This is &amp;ldquo;I used Neon as a metadata store for a small educational app.&amp;rdquo; Keep that context in mind.&lt;/p&gt;
&lt;h2 id=&#34;what-i-was-actually-running&#34;&gt;What I Was Actually Running&lt;/h2&gt;
&lt;p&gt;The traffic pattern looked like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;50-100 concurrent users during exam prep peaks&lt;/li&gt;
&lt;li&gt;Each user session: load homepage (one query for aggregate stats - yes, I could have cached this but I was lazy), fetch problem set list (one query), load problem set metadata (one query), load all problems in that set (one query)&lt;/li&gt;
&lt;li&gt;Peak query rate: probably 10-20 queries per second, ballpark&lt;/li&gt;
&lt;li&gt;Total data volume: laughably small, maybe 50MB including all the problem descriptions&lt;/li&gt;
&lt;li&gt;No complex joins, no aggregations, just basic CRUD on small tables&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The application server ran on Fly.io (legacy free tier, Singapore region because they don&amp;rsquo;t let me deploy in India). Neon database also in Singapore since they don&amp;rsquo;t have an India region. This meant server-to-database latency was negligible, which matters more than client-to-server latency for this architecture.&lt;/p&gt;
&lt;h2 id=&#34;the-good-parts&#34;&gt;The Good Parts&lt;/h2&gt;
&lt;p&gt;Cold starts are legitimately fast. I measured a few wake-ups from scale-to-zero: consistently under 1 second from first query to response. For my use case where users might access the site after a few hours of inactivity, this was completely acceptable. Nobody noticed.&lt;/p&gt;
&lt;p&gt;Database provisioning is instant. Supabase takes 2-3 minutes to spin up a new project. Neon takes 5-10 seconds.&lt;/p&gt;
&lt;p&gt;Branching is as advertised. I used it to create a dev copy of production data for testing new problem sets. The branch showed up in under 10 seconds, and I could connect to it immediately. I didn&amp;rsquo;t use any fancy &amp;ldquo;branch per feature&amp;rdquo; workflows - just treated it as a really fast database clone. That alone was useful.&lt;/p&gt;
&lt;p&gt;Connection quality from TablePlus was surprisingly good. I&amp;rsquo;m in Kolkata, database is in Singapore, and there was no perceptible lag when browsing tables or running manual queries. For comparison, when I&amp;rsquo;ve used Supabase instances hosted in Mumbai, there&amp;rsquo;s a noticeable delay on every interaction in TablePlus. With Neon in Singapore, it felt instant. I don&amp;rsquo;t know if this is connection pooling magic or better routing or what, but it made admin work much smoother.&lt;/p&gt;
&lt;p&gt;The serverless driver handled reconnections gracefully. When the compute scaled down and back up, my application code didn&amp;rsquo;t notice. No error handling needed, no retry logic, just worked. Compare this to using a direct psql connection: when the compute scales down, you get an &amp;ldquo;SSL connection has been closed unexpectedly&amp;rdquo; error, then it auto-reconnects after a few seconds. Functional but ugly.&lt;/p&gt;
&lt;h2 id=&#34;the-tradeoffs&#34;&gt;The Tradeoffs&lt;/h2&gt;
&lt;p&gt;No India region. For my users (all in India), this added latency. Hard to measure exactly since the app is lightweight, but it&amp;rsquo;s not ideal. Singapore was acceptable but not optimal.&lt;/p&gt;
&lt;p&gt;The serverless driver is noticeably slower than direct Postgres. I didn&amp;rsquo;t benchmark this rigorously, but subjectively, queries that should return in 10-20ms via direct connection felt like 50-100ms via the serverless driver. This is the cost of the pooling/scaling architecture. For my workload, it didn&amp;rsquo;t matter. For something latency-sensitive, you&amp;rsquo;d feel it.&lt;/p&gt;
&lt;p&gt;Query metrics reset when compute scales to zero. This is both unexpected, and annoying. You can&amp;rsquo;t track query patterns over time because the dashboard wipes clean after each scale-down. If you&amp;rsquo;re trying to optimize slow queries or understand usage patterns, you&amp;rsquo;re out of luck unless you set up external monitoring.&lt;/p&gt;
&lt;p&gt;Connection pooling limit is per-project. The serverless driver supports 10,000 pooled connections, which sounds like a lot until you realize it&amp;rsquo;s shared across all clients accessing that project. My usage never exceeded a single connection, so I can&amp;rsquo;t speak to what happens near the limit, but it&amp;rsquo;s worth knowing the boundary exists.&lt;/p&gt;
&lt;h2 id=&#34;thoughts-on-pricing&#34;&gt;Thoughts on Pricing&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s where Neon&amp;rsquo;s model gets weird.&lt;/p&gt;
&lt;p&gt;The free tier gives you 80 projects, each with 100 compute-unit hours per month. That sounds generous: 80 × 100 = 8,000 CU-hours total.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s a catch: &lt;strong&gt;you cannot pool these hours across projects.&lt;/strong&gt; Each project gets exactly 100 CU-hours, period. You can&amp;rsquo;t run one project for 800 hours and leave the others idle.&lt;/p&gt;
&lt;p&gt;The minimum compute size is 0.25 CU. A month has ~750 hours. Do the math: 100 CU-hours ÷ 0.25 CU = 400 hours maximum. &lt;strong&gt;You cannot run even a single free-tier project 24/7.&lt;/strong&gt; You&amp;rsquo;d hit the cap halfway through the month.&lt;/p&gt;
&lt;p&gt;This would be fine if serverless actually scaled to zero in practice. But here&amp;rsquo;s what I learned the hard way:&lt;/p&gt;
&lt;h3 id=&#34;serverless-databases-require-frontend-discipline&#34;&gt;Serverless Databases Require Frontend Discipline&lt;/h3&gt;
&lt;p&gt;Even one user being online keeps the compute running.&lt;/p&gt;
&lt;p&gt;I forgot to disable React Query&amp;rsquo;s automatic background refetching. The default behavior polls the API every few minutes when the window is focused, and refetches on tab focus. This meant anyone leaving the homepage open - even if they weren&amp;rsquo;t actively using it - would keep hitting the backend, which kept the database compute alive.&lt;/p&gt;
&lt;p&gt;A single browser tab, sitting idle on someone&amp;rsquo;s screen, was enough to prevent scale-to-zero from ever triggering.&lt;/p&gt;
&lt;p&gt;This is the fundamental thing about serverless databases that nobody emphasizes: &lt;strong&gt;your database doesn&amp;rsquo;t scale to zero because it&amp;rsquo;s idle. It scales to zero when clients stop making requests.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With a traditional VPS running Postgres, your frontend behavior doesn&amp;rsquo;t affect hosting costs. A $5 VPS costs $5 whether your React app polls every second or stays silent for hours. Serverless inverts this. Every automatic refetch, every &amp;ldquo;check for updates&amp;rdquo; feature, every WebSocket keepalive becomes a line item on your infrastructure costs.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re building on serverless infrastructure, audit your frontend&amp;rsquo;s network behavior:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disable automatic refetching unless you genuinely need real-time data&lt;/li&gt;
&lt;li&gt;Use longer polling intervals (or better: don&amp;rsquo;t poll at all, use manual refresh)&lt;/li&gt;
&lt;li&gt;Think about what happens when users leave tabs open for hours&lt;/li&gt;
&lt;li&gt;Consider whether that &amp;ldquo;sync on window focus&amp;rdquo; behavior is worth keeping the database awake&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The backend being &amp;ldquo;serverless&amp;rdquo; is irrelevant if your frontend keeps it awake 24/7.&lt;/p&gt;
&lt;h3 id=&#34;my-actual-usage&#34;&gt;My Actual Usage&lt;/h3&gt;
&lt;p&gt;Over the 5-day exam prep period, I used about 25 CU-hours. Compute was active almost 24 hours a day for that period. I stayed comfortably within the 100 CU-hour monthly limit.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s the thing: I spent way too much mental energy worrying about it. Watching the number climb in the Neon dashboard, not knowing when students would be active, wondering if someone had a tab open and was quietly burning through my allocation - the &amp;ldquo;serverless&amp;rdquo; cost model added stress that a fixed $5/month VPS wouldn&amp;rsquo;t have.&lt;/p&gt;
&lt;p&gt;For anyone considering Neon for similar usage: 50-100 concurrent users doing light reads will use roughly 5 CU-hours per day if the compute stays mostly active. Scale accordingly.&lt;/p&gt;
&lt;h3 id=&#34;the-paid-tier-math&#34;&gt;The Paid Tier Math&lt;/h3&gt;
&lt;p&gt;Running one database continuously at minimum compute (0.25 CU) would cost about $20/month:&lt;/p&gt;
&lt;p&gt;0.25 CU × 750 hours × $0.106/CU-hour ≈ $20&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s steep for hobby projects. Neon&amp;rsquo;s marketing targets indie developers and side projects, but the economics don&amp;rsquo;t support always-on applications at that scale. A $5 DigitalOcean droplet running Postgres would be way cheaper, though you&amp;rsquo;d handle your own backups, scaling, and operations.&lt;/p&gt;
&lt;h2 id=&#34;would-i-use-it-again&#34;&gt;Would I Use It Again?&lt;/h2&gt;
&lt;p&gt;For this specific use case - a platform serving metadata during a concentrated exam period with real idle gaps - Neon worked well. The cold start performance didn&amp;rsquo;t hurt user experience, database provisioning was smooth, and the connection quality made development pleasant.&lt;/p&gt;
&lt;p&gt;For a project that needs to run continuously, I&amp;rsquo;d probably look elsewhere. The serverless architecture makes sense for workloads with genuine idle periods, but the reality is that even sporadic traffic prevents scale-to-zero from being useful. The per-project compute caps and pricing make it less attractive for always-on applications than traditional hosting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where Neon actually makes sense:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scheduled jobs that run a few times per day (data processing, reports, maintenance scripts)&lt;/li&gt;
&lt;li&gt;Dev/staging environments that only spin up during work hours&lt;/li&gt;
&lt;li&gt;Bursty workloads with predictable idle periods (weekly reports, monthly processing)&lt;/li&gt;
&lt;li&gt;Projects where you value operational simplicity over cost optimization&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Where I&amp;rsquo;d think twice:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Always-on production apps with steady traffic&lt;/li&gt;
&lt;li&gt;Anything latency-sensitive (use direct Postgres, not the serverless driver)&lt;/li&gt;
&lt;li&gt;High query volume applications where you need persistent metrics&lt;/li&gt;
&lt;li&gt;Projects where you can&amp;rsquo;t enforce strict frontend discipline around polling/refetching&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So yeah, I&amp;rsquo;d probably use Neon again, but I&amp;rsquo;d probably reach for SQLite first. The technology works as advertised. The pricing model just doesn&amp;rsquo;t align well with how real applications behave in the wild.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;The platform is live at &lt;a class=&#34;link&#34; href=&#34;https://oppe.dev&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;oppe.dev&lt;/a&gt; if you want to check it out. Part 2 will cover the WASM SQL execution setup, why I went that route, and the cursed things I had to do to get Python in WASM to talk to a PGLite database running in the browser.&lt;/em&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to Handle &#34;Bracket&#34; Array Query Parameters (key[]=val) in FastAPI</title>
        <link>https://ishan.page/blog/fastapi-query-arrays/</link>
        <pubDate>Thu, 27 Nov 2025 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/fastapi-query-arrays/</guid>
        <description>&lt;p&gt;FastAPI expects array parameters in the standard &lt;code&gt;key=v1&amp;amp;key=v2&lt;/code&gt; format. However, many frontend client generators like my favourite, &lt;strong&gt;Orval&lt;/strong&gt;, default to &lt;code&gt;key[]=v1&amp;amp;key[]=v2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you cannot change the client configuration, FastAPI will fail to validate these lists.&lt;/p&gt;
&lt;p&gt;The fix is to add a middleware that strips the brackets from keys before the request reaches the routing layer.&lt;/p&gt;
&lt;h2 id=&#34;the-code&#34;&gt;The Code&lt;/h2&gt;
&lt;p&gt;This middleware intercepts the HTTP scope, reconstructs the &lt;code&gt;query_string&lt;/code&gt;, and ensures it is re-encoded to &lt;code&gt;bytes&lt;/code&gt; to avoid &lt;code&gt;AttributeError: &#39;str&#39; object has no attribute &#39;decode&#39;&lt;/code&gt; errors in Uvicorn.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FastAPI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.datastructures&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QueryParams&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;FixListQueryParamsMiddleware&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__call__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;receive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# Adapted from https://github.com/fastapi/fastapi/discussions/7827#discussioncomment-5144572&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;receive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# Rebuild params: strip &amp;#34;[]&amp;#34; from keys ending with it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;new_items&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;endswith&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;[]&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query_params&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;multi_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;query_string&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;QueryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ascii&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;receive&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;p&gt;Register the class directly in your FastAPI app initialization:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FastAPI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_middleware&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FixListQueryParamsMiddleware&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/users&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_users&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ids&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Request: GET /users?ids[]=1&amp;amp;ids[]=2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Result: ids=[1, 2]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ids&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;em&gt;Context: See &lt;a class=&#34;link&#34; href=&#34;https://github.com/fastapi/fastapi/discussions/7827&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;FastAPI Discussion #7827&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to Force Google Calendar Account Picker When Adding ICS Subscriptions</title>
        <link>https://ishan.page/blog/google-calendar-account-picker/</link>
        <pubDate>Wed, 26 Nov 2025 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/google-calendar-account-picker/</guid>
        <description>&lt;p&gt;If you share a link that lets people subscribe to an &lt;code&gt;.ics&lt;/code&gt; feed in Google Calendar, you’ve probably seen this pattern:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;https://calendar.google.com/calendar/render?cid=webcal://your-feed.ics
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It works, but there’s a catch:
If the user is logged into multiple Google accounts, Google just picks one. No warning. No choice. Easy way to end up adding the calendar to the wrong account.&lt;/p&gt;
&lt;p&gt;Here’s the fix.&lt;/p&gt;
&lt;h2 id=&#34;use-accountchooser-to-force-the-picker&#34;&gt;Use AccountChooser to Force the Picker&lt;/h2&gt;
&lt;p&gt;Google has a built-in account picker page. If you send users through it first, they &lt;em&gt;will&lt;/em&gt; be asked which account to use before they land in Calendar.&lt;/p&gt;
&lt;p&gt;Wrap your calendar URL like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;https://accounts.google.com/AccountChooser?continue=https://calendar.google.com/calendar/render?cid=webcal://your-feed.ics
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That’s it. Clicking this link always shows the account picker, then kicks the user over to the Calendar subscribe screen.&lt;/p&gt;
&lt;h2 id=&#34;why-this-works&#34;&gt;Why This Works&lt;/h2&gt;
&lt;p&gt;Calendar doesn’t expose a “show picker” flag. AccountChooser does. It pauses the flow, lets the user choose an account, and then continues to whatever URL you gave it.&lt;/p&gt;
&lt;h2 id=&#34;make-your-own-accountchooser-link&#34;&gt;Make Your Own AccountChooser Link&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a quick tool to generate your own AccountChooser-enabled calendar subscription links:&lt;/p&gt;
&lt;script src=&#34;https://unpkg.com/alpinejs&#34; defer&gt;&lt;/script&gt;
&lt;script&gt;
document.addEventListener(&#39;alpine:init&#39;, () =&gt; {
  Alpine.data(&#39;accountChooserTool&#39;, () =&gt; ({
    icsUrl: &#39;https://example.com/calendar.ics&#39;,
    getEncodedLink() {
      // Remove scheme (http://, https://, webcal://, etc.) if present
      const effectiveIcsUrl = this.icsUrl.replace(/^(https?:|webcal:)\/\//, &#39;&#39;);
      const calendarUrl = `https://calendar.google.com/calendar/render?cid=webcal://${effectiveIcsUrl}`;
      const encodedCalendarUrl = encodeURIComponent(calendarUrl);
      return `https://accounts.google.com/AccountChooser?continue=${encodedCalendarUrl}`;
    }
  }))
})
&lt;/script&gt;
&lt;style&gt;
input, textarea {
  font-family: monospace !important;
  display: block;
  background-color: var(--pre-background-color);
  color: var(--pre-text-color);
  width: 100%;
}

button {
  background: var(--accent-color);
  box-shadow: var(--shadow-l2);
  border-radius: var(--tag-border-radius);
  padding: 8px 20px;
  color: var(--accent-color-text);
  font-size: 1.4rem;
  transition: all .3s ease;
  border: 0;
  cursor: pointer;
}

button:hover {
  background: var(--accent-color-darker);
}

.flex-col {
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
}
&lt;/style&gt;
&lt;div x-data=&#34;accountChooserTool&#34;&gt;
&lt;div class=&#34;flex-col&#34;&gt;
&lt;label for=&#34;icsUrl&#34;&gt;Your ICS URL:&lt;/label&gt;
&lt;input type=&#34;text&#34; id=&#34;icsUrl&#34; x-model=&#34;icsUrl&#34;&gt;
&lt;/div&gt;
&lt;div class=&#34;flex-col&#34;&gt;
&lt;label&gt;Your AccountChooser Link:&lt;/label&gt;
&lt;textarea x-text=&#34;getEncodedLink()&#34; style=&#34;height: 80px;&#34; readonly&gt;&lt;/textarea&gt;
&lt;/div&gt;
&lt;button @click=&#34;navigator.clipboard.writeText(getEncodedLink())&#34;&gt;Copy to Clipboard&lt;/button&gt;
&lt;/div&gt;
&lt;h2 id=&#34;when-to-use-it&#34;&gt;When to Use It&lt;/h2&gt;
&lt;p&gt;Anytime you expect users to have more than one Google account (so… basically always), and you don’t want support emails about “Why did this add to my work calendar?”&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Easy alias for dealing with Python Virtualenvs</title>
        <link>https://ishan.page/blog/easy-venv-script/</link>
        <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/easy-venv-script/</guid>
        <description>&lt;p&gt;There’s something oddly comforting about a shell function that takes care of boring things for you.&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;venv()&lt;/code&gt; helper does exactly that.&lt;/p&gt;
&lt;p&gt;It checks whether you’re already in an environment, spins up a fresh one if needed, installs your dependencies, and activates it.&lt;/p&gt;
&lt;p&gt;To use this &lt;code&gt;venv&lt;/code&gt; function, you’ll need to add it to your shell’s configuration file. If you’re using zsh, add the following function to your ~/.zshrc file. If you’re using bash, add it to your ~/.bashrc instead.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget to &lt;code&gt;source ~/.zshrc&lt;/code&gt; or &lt;code&gt;source ~/.bashrc&lt;/code&gt; later!&lt;/p&gt;
&lt;p&gt;This requires &lt;code&gt;uv&lt;/code&gt; to work&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;venv&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# Exit early if already in a virtual environment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;A virtual environment is already active at: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$VIRTUAL_ENV&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# Create .venv if missing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; ! -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;.venv&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Creating virtual environment...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    uv venv &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Failed to create venv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Install dependencies if requirements.txt exists&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; -f &lt;span class=&#34;s2&#34;&gt;&amp;#34;requirements.txt&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Installing dependencies...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      uv pip install -r requirements.txt &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Dependency install failed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;No requirements.txt found; skipping installation.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# Activate the environment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; .venv/bin/activate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Of course, if you use &lt;code&gt;uv run&lt;/code&gt; for running things anyway, then you don&amp;rsquo;t need this!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>I’m an IIT Madras Student. But to Some, I’m Diluting the Brand.</title>
        <link>https://ishan.page/blog/jeeification/</link>
        <pubDate>Fri, 31 Oct 2025 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/jeeification/</guid>
        <description>&lt;p&gt;I have a confession to make.&lt;/p&gt;
&lt;p&gt;Before I was a student at IIT Madras, I hated it.&lt;/p&gt;
&lt;p&gt;For years, the letters &amp;ldquo;I-I-T&amp;rdquo; were a trigger, a symbol of a world I wasn&amp;rsquo;t welcome in: a club with gates so high I couldn’t even pretend to scale them. It left a bitter taste in my mouth.&lt;/p&gt;
&lt;p&gt;This wasn’t an abstract dislike; it was a deeply personal one, forged in the crucible of teenage grief and necessity.&lt;/p&gt;
&lt;p&gt;My story isn’t the one you’ve seen in coaching center posters. I first learned to code in 2012, not to crack an exam, but out of raw curiosity, the kind that comes from discovery, not strategy.&lt;/p&gt;
&lt;p&gt;That curiosity became a lifeline in 2016. I was 15 when my father passed away, and the predictable path my life was supposed to follow &amp;ndash; school, college, career &amp;ndash; shattered overnight. While my peers were losing themselves in the labyrinth of H.C. Verma and I.E. Irodov, I was juggling freelance coding projects, trying to help my family stay afloat.&lt;/p&gt;
&lt;p&gt;From 2017 to 2020, irony became my daily companion.&lt;/p&gt;
&lt;p&gt;I was a software developer at an EdTech company. A company that coached thousands of teenagers for the JEE.&lt;/p&gt;
&lt;p&gt;I was, in a sense, a builder of the very dream I had failed to attain. I gave the exam a shot, of course. It felt like a rite of passage.&lt;/p&gt;
&lt;p&gt;But my mind, occupied with work, grief, and the weight of adult responsibility, wasn’t wired for that brutal, all-or-nothing, three-hour performance. I failed, and I failed decisively.&lt;/p&gt;
&lt;p&gt;The sting of that rejection was real.&lt;/p&gt;
&lt;p&gt;It came not from failure itself, but from the quiet pity in relatives’ eyes and the invisible social judgment that comes from missing the one exam our society worships.&lt;/p&gt;
&lt;p&gt;To cope, I built a fortress of cynicism. “The IITs are just factories for rote learners,” I’d tell anyone who’d listen. “They don’t value real-world skills.” It was a textbook case of sour grapes: a defense mechanism against a system that had deemed me unworthy.&lt;/p&gt;
&lt;p&gt;Life moved on.&lt;/p&gt;
&lt;p&gt;And then, I found a different door: the &lt;a class=&#34;link&#34; href=&#34;https://study.iitm.ac.in/ds/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;IIT Madras BS Degree in Data Science and Applications&lt;/a&gt;. It wasn’t a consolation prize. It was a pragmatic, modern reinvention of higher education. It was a way for people like me to rejoin the conversation.&lt;/p&gt;
&lt;p&gt;I enrolled. I was proud.&lt;/p&gt;
&lt;p&gt;And then, through Reddit threads, Discord servers, and WhatsApp groups, I learned that to a vocal group of on-campus students, I wasn’t a fellow IITian.&lt;/p&gt;
&lt;p&gt;I was an imposter, a “brand diluter.”&lt;/p&gt;
&lt;p&gt;This is my story, but it’s bigger than me. It’s about a deep cultural sickness, a phenomenon I call &lt;strong&gt;“JEE-ification.”&lt;/strong&gt; And it’s one that’s beginning to have global consequences.&lt;/p&gt;
&lt;h2 id=&#34;from-cracking-jee-to-tarnishing-made-in-india&#34;&gt;From &amp;ldquo;Cracking JEE&amp;rdquo; To Tarnishing &amp;ldquo;Made in India&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;“JEE-ification” is more than an obsession with one exam. It’s a way of life: the belief that learning is a zero-sum conquest of filters, not a lifelong journey of discovery.&lt;/p&gt;
&lt;p&gt;The goal isn’t knowledge; it’s rank. The reward isn’t mastery; it’s entry into an exclusive club.
The entire prestige of that club derives not from what’s inside, but from how many people are kept out.&lt;/p&gt;
&lt;p&gt;It’s worth acknowledging that the JEE once had real intellectual legitimacy. It was designed as a filter for rigor, to identify those who could reason abstractly under pressure, not to manufacture exclusion.&lt;/p&gt;
&lt;p&gt;But over time, that rigor decayed into a fetish for gatekeeping. The metric replaced the mission.&lt;/p&gt;
&lt;p&gt;And that mindset has metastasized.&lt;/p&gt;
&lt;p&gt;You see it in the explosion of “bhaiya/didi” coding channels on YouTube. They don’t teach the beauty of algorithms or the architecture of systems; they teach “roadmaps.” They sell “crash courses” to “crack FAANG in six months.”&lt;/p&gt;
&lt;p&gt;I watch these &amp;lsquo;roadmap&amp;rsquo; videos with a sense of mourning.&lt;/p&gt;
&lt;p&gt;They are selling a cheap forgery of the very thing that saved me: the joy of discovery. They&amp;rsquo;ve turned a boundless landscape of intellectual play into a grim, linear treadmill.&lt;/p&gt;
&lt;p&gt;It feels like watching someone reduce a grand symphony to a list of notes to memorize for a test.&lt;/p&gt;
&lt;p&gt;It’s a vocabulary of shortcuts.&lt;/p&gt;
&lt;p&gt;The tragedy of the ‘roadmap coder’ isn’t that they’re &amp;ldquo;lazy&amp;rdquo;. It’s that they’ve been trained to see code as a ladder rather than a language.&lt;/p&gt;
&lt;p&gt;They don’t ask, &amp;ldquo;what can I build?&amp;rdquo; but &amp;ldquo;what will this get me?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The most visible symptoms of this culture were the Express.js and Hacktoberfest incidents.&lt;/p&gt;
&lt;p&gt;During Hacktoberfest, a global event to encourage open-source contribution, a popular Indian YouTube channel, CodeWithHarry, in a now edited video, &lt;a class=&#34;link&#34; href=&#34;https://joel.net/how-one-guy-ruined-hacktoberfest2020-drama&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;urged his followers to participate&lt;/a&gt; with the tagline &amp;ldquo;t-shirt loot lo&amp;rdquo; (Go loot the t-shirt).&lt;/p&gt;
&lt;p&gt;The result was predictable: maintainers of projects worldwide were inundated with low-effort, spammy pull requests.&lt;/p&gt;
&lt;p&gt;Shortly after, &lt;a class=&#34;link&#34; href=&#34;https://socket.dev/blog/express-js-spam-prs-commoditization-of-open-source&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;a similar channel unleashed thousands of followers on Express.js&lt;/a&gt;, one of the world’s most critical software projects.&lt;/p&gt;
&lt;p&gt;The goal was again credit, not contribution, leading to a flood of pull requests editing README files just to add a name.&lt;/p&gt;
&lt;p&gt;These students weren’t malicious; they were doing exactly what they’d been trained to do: optimize for a visible credential, be it a limited-edition t-shirt or a green square on their GitHub profile.&lt;/p&gt;
&lt;p&gt;But the consequence was global embarrassment. It reinforced the stereotype of the “Indian developer” as someone who games systems rather than contributes meaningfully. The tragedy is that this reputation harms the countless Indian engineers who do build, innovate, and sustain open-source ecosystems with integrity.&lt;/p&gt;
&lt;p&gt;This is the endgame of JEE-ification: a culture that values the &lt;em&gt;badge&lt;/em&gt; over the &lt;em&gt;building&lt;/em&gt;, and in the process, tarnishes both.&lt;/p&gt;
&lt;p&gt;And when your sense of identity has been forged entirely in that fire, when your self-worth comes from having survived that one gate, any attempt to open new doors feels like an existential threat. It feels like a rug-pull.&lt;/p&gt;
&lt;h2 id=&#34;the-purpose-of-a-jee-is-who-it-selects&#34;&gt;The Purpose Of A JEE Is Who It Selects&lt;/h2&gt;
&lt;p&gt;In systems thinking, there&amp;rsquo;s a powerful principle known as &lt;a class=&#34;link&#34; href=&#34;https://joelitobarski.com/posiwid/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;POSIWID&lt;/a&gt;: The Purpose Of a System Is What It Does.&lt;/p&gt;
&lt;p&gt;It’s a simple but profound idea. You don&amp;rsquo;t judge a system by its stated goals or the intentions of its designers; you judge it by its actual, observable outcomes.&lt;/p&gt;
&lt;p&gt;If we apply this lens to the Joint Entrance Examination, the conclusion is unsettling.&lt;/p&gt;
&lt;p&gt;The stated purpose of the JEE is to identify the most promising scientific and engineering minds in the nation. But what does it actually do? Who does it consistently, year after year, select?&lt;/p&gt;
&lt;p&gt;It selects for incredible resilience, pattern recognition, and the ability to perform under crushing, single-event pressure. These are not trivial skills. But it also overwhelmingly selects for a specific type of mind and, often, a specific life circumstance.&lt;/p&gt;
&lt;p&gt;It selects for solvers of well-defined problems, not finders of ambiguous ones. It rewards optimizers of a known system, not builders of new ones. It filters for those who can afford the luxury of a multi-year, single-minded focus on exam preparation, a luxury my own life story shows is not available to everyone.&lt;/p&gt;
&lt;p&gt;And by extension, who does it select against?&lt;/p&gt;
&lt;p&gt;It selects against the curious tinkerer who spent their teens building open-source projects instead of memorizing reaction mechanisms. It selects against the early-career professional who discovered a passion for technology only after a family crisis forced them into the workforce. It selects against the brilliant student from a remote town who lacked access to the multi-lakh-rupee Kota ecosystem.&lt;/p&gt;
&lt;p&gt;The JEE doesn’t just test for aptitude; it tests for a very specific, privileged, and linear life path.&lt;/p&gt;
&lt;p&gt;When we deify the exam, we are implicitly devaluing all other paths to knowledge and competence. This isn&amp;rsquo;t a selection for broad excellence; it&amp;rsquo;s a selection for a narrow kind of conformity.&lt;/p&gt;
&lt;p&gt;And that is the very engine of JEE-ification. It creates a cohort whose identity is forged by this one shared, exclusionary trial. When your entire sense of achievement is based on having survived that filter, anyone who arrives through a different door doesn&amp;rsquo;t just feel like a peer; they feel like a bug in the system.&lt;/p&gt;
&lt;p&gt;In a developing nation where scarcity and signaling dominate opportunity, the exam became not just a filter for competence, but a proxy for self-worth and employability.&lt;/p&gt;
&lt;h2 id=&#34;the-author-is-a-platypus&#34;&gt;The Author Is A Platypus&lt;/h2&gt;
&lt;p&gt;I have to acknowledge the irony in all this.&lt;/p&gt;
&lt;p&gt;I’ve spent paragraphs critiquing credentialism, while pursuing one of the most recognizable credentials in India.&lt;/p&gt;
&lt;p&gt;It’s fair to call that hypocrisy. But it’s also reality.&lt;/p&gt;
&lt;p&gt;Because even when you see the gate for what it is, you still feel compelled to walk through it. The world keeps too many keys on the other side.&lt;/p&gt;
&lt;p&gt;When I joined the IIT Madras BS program, it wasn’t just for curiosity or intellectual revival.&lt;/p&gt;
&lt;p&gt;Part of me wanted legitimacy: to reclaim something I’d been denied.&lt;/p&gt;
&lt;p&gt;To prove, if only to myself, that I could belong to the club whose doors once stayed shut.&lt;/p&gt;
&lt;p&gt;That’s how deep the conditioning runs.&lt;/p&gt;
&lt;p&gt;We don’t just internalize the exam; we internalize the need for permission. Even when we try to unlearn the system, its incentives shape our choices.&lt;/p&gt;
&lt;p&gt;You can critique the hierarchy and still crave its approval.&lt;/p&gt;
&lt;p&gt;Maybe that’s what growing up in a credential-obsessed culture does to you. Awareness doesn’t grant immunity; it only makes the infection visible.&lt;/p&gt;
&lt;p&gt;But perhaps naming the hypocrisy is the first honest step toward escaping it.&lt;/p&gt;
&lt;h2 id=&#34;life-as-a-brand-diluter&#34;&gt;Life As A &amp;ldquo;Brand Diluter&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;If people think we’re on “easy mode,” they’re living in a fantasy. The IIT Madras BS degree is not a backdoor.&lt;/p&gt;
&lt;p&gt;First, &lt;strong&gt;our program has its own brutal meritocracy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It’s not a one-shot exam, but a continuous, multi-year test of endurance.&lt;/p&gt;
&lt;p&gt;I’ve been a professional software engineer for almost a decade, and the foundational Maths 2 course still took me nearly a year (three terms) to clear.&lt;/p&gt;
&lt;p&gt;The attrition rate is enormous. Many bright students never make it past the foundation level.&lt;/p&gt;
&lt;p&gt;If this is “brand dilution,” it’s the most demanding kind imaginable.&lt;/p&gt;
&lt;p&gt;Second, &lt;strong&gt;we don’t consume campus resources.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We exist in parallel: separate instructors, separate TAs, separate infrastructure.&lt;/p&gt;
&lt;p&gt;Our placement cell operates independently from the on-campus placement ecosystem.&lt;/p&gt;
&lt;p&gt;We are not your competition. The conflict exists more in memes and myths than in reality.&lt;/p&gt;
&lt;p&gt;Third, &lt;strong&gt;our community is our strength.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our WhatsApp groups are alive at 3 AM with students helping one another: a professional in Bangalore tutoring a teenager in Bihar on statistics.&lt;/p&gt;
&lt;p&gt;It’s a microcosm of what democratized higher education can look like. We also know the system isn’t perfect.&lt;/p&gt;
&lt;p&gt;But we persist. Because the idea is worth the friction.&lt;/p&gt;
&lt;h2 id=&#34;the-psychology-of-exclusivity&#34;&gt;The Psychology of Exclusivity&lt;/h2&gt;
&lt;p&gt;Sociologists would call it &lt;a class=&#34;link&#34; href=&#34;https://dailyimprovisation.blogspot.com/2016/09/status-scarcity-and-academic-publishing.html?m=1&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;em&gt;status scarcity&lt;/em&gt;&lt;/a&gt;: when prestige is finite, identity becomes a zero-sum game.&lt;/p&gt;
&lt;p&gt;If the IIT brand once meant “I passed an impossible test,” then any alternative path, no matter how rigorous, threatens to dilute the currency of that identity.&lt;/p&gt;
&lt;p&gt;The fear is existential, not rational. When the club grows, members mistake expansion for erosion.&lt;/p&gt;
&lt;p&gt;But the truth is simpler: excellence is not a finite resource. Widening access doesn’t cheapen quality; it amplifies impact.&lt;/p&gt;
&lt;p&gt;The brand of an IIT should come from what it builds, not who it excludes.&lt;/p&gt;
&lt;h2 id=&#34;an-iit-is-for-nation-building&#34;&gt;An IIT Is For Nation Building&lt;/h2&gt;
&lt;p&gt;If we’re not a threat, and our program is just as rigorous, why does the “brand dilution” myth persist?&lt;/p&gt;
&lt;p&gt;Because somewhere along the way, we forgot what IITs were founded for.&lt;/p&gt;
&lt;p&gt;Let’s revisit the source. The &lt;a class=&#34;link&#34; href=&#34;https://www.iitm.ac.in/the-institute/about-iit-madras/mission&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;mission of IIT Madras&lt;/a&gt; commits to (emphasis mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;advancement of knowledge through education and research&lt;/strong&gt;, in both Pure and Applied Science, in Engineering, Social Science and Humanities;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;service to the community and nation&lt;/strong&gt; (which are referred to as Extension activity) through the use of their resources both intellectual and material, &lt;strong&gt;particularly through Continuing Education for professionals working in Industry.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;That’s not fine print. It’s the institution’s DNA. The BS degree is not an afterthought or a side hustle. It’s the 21st-century expression of that mission.&lt;/p&gt;
&lt;p&gt;The IIT system itself was born as a postcolonial project of nation-building modeled on MIT and Soviet technical universities, meant to empower a newly independent India with technological self-sufficiency.&lt;/p&gt;
&lt;p&gt;Its purpose was not elitism; it was capacity-building. To educate not the few, but the &lt;em&gt;capable&lt;/em&gt;. The BS program extends that legacy into the digital era.&lt;/p&gt;
&lt;p&gt;And leaders outside the campus bubble already recognize this. Senior IIT alumni, multinational executives, and civil servants I’ve spoken with don’t see “brand dilution.”&lt;/p&gt;
&lt;p&gt;They see strategic national value: a model that discovers hidden talent in small towns, mid-career professionals, and working mothers whom the JEE system overlooks by design.&lt;/p&gt;
&lt;h2 id=&#34;a-message-to-the-gatekeepers&#34;&gt;A Message To The Gatekeepers&lt;/h2&gt;
&lt;p&gt;To the skeptical on-campus student reading this: I understand you. I used to think like you.&lt;/p&gt;
&lt;p&gt;My early cynicism toward IIT was born of exclusion; your defensiveness is born of exclusivity. They are mirror images of the same fear: fear that value must always be &lt;em&gt;protected&lt;/em&gt; rather than &lt;em&gt;created.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And here’s the uncomfortable symmetry: your fixation on preserving the “IIT tag” is not so different from the “roadmap coder” obsessed with a FAANG job.&lt;/p&gt;
&lt;p&gt;Both see learning as a means to a credential, not a craft. Both conflate gates with greatness.&lt;/p&gt;
&lt;p&gt;In fact, this obsession with the entry gate over the actual discipline is so pervasive that many on-campus students in core engineering fields spend their four years preparing for software roles, effectively devaluing their own &amp;ldquo;brand&amp;rdquo; and degree in pursuit of the same CS-centric credentialism.&lt;/p&gt;
&lt;p&gt;The system has taught you that the entry point matters more than the field of study. This isn&amp;rsquo;t a failure of students; it&amp;rsquo;s a failure of the culture that &amp;ldquo;JEE-ification&amp;rdquo; has built.&lt;/p&gt;
&lt;p&gt;My success does not diminish yours. But your gatekeeping diminishes what the IITs can become.&lt;/p&gt;
&lt;p&gt;If we could bridge the gap. If on-campus students and BS learners collaborated on research, startups, and open-source projects, IIT Madras could become not just a symbol of excellence, but a prototype for scalable, inclusive education worldwide. A model where rigor meets reach.&lt;/p&gt;
&lt;p&gt;Because the strength of the IIT brand in this century will not be measured by the height of its walls,
&lt;strong&gt;but by the length of its reach.&lt;/strong&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Easy Jigsaw Puzzle Embed for Your Website</title>
        <link>https://ishan.page/blog/jigsaw-puzzle-embed/</link>
        <pubDate>Tue, 22 Apr 2025 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/jigsaw-puzzle-embed/</guid>
        <description>&lt;script src=&#34;https://unpkg.com/alpinejs&#34; defer&gt;&lt;/script&gt;
&lt;p&gt;I wanted to share a small project I&amp;rsquo;ve been working on - a simple jigsaw puzzle embed that you can add to any website.&lt;/p&gt;
&lt;h2 id=&#34;what-it-does&#34;&gt;What It Does&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s a straightforward tool that lets you embed customizable jigsaw puzzles into your web pages. You can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use any image as the puzzle&lt;/li&gt;
&lt;li&gt;Choose the background color&lt;/li&gt;
&lt;li&gt;Set the difficulty by adjusting the number of pieces&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When someone completes the puzzle, it sends a &amp;ldquo;puzzleSolved&amp;rdquo; message that your site can detect.&lt;/p&gt;
&lt;h2 id=&#34;how-to-add-it&#34;&gt;How to Add It&lt;/h2&gt;
&lt;p&gt;Just include this iframe in your HTML:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;iframe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;na&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://jigsaw.ishan.page?img=https://example.com/your-image.jpg&amp;amp;bg=ffffff&amp;amp;pieces=25&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;na&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;600&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;na&#34;&gt;height&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;400&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;na&#34;&gt;frameborder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;detecting-when-the-puzzle-is-solved&#34;&gt;Detecting When the Puzzle is Solved&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a simple code example to detect when someone completes your puzzle:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;addEventListener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// The puzzle uses parent.postMessage(&amp;#34;puzzleSolved&amp;#34;,&amp;#34;*&amp;#34;) when completed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;event&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;puzzleSolved&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Puzzle completed!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Do something when the puzzle is solved
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;try-it-out&#34;&gt;Try It Out&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a live configurator where you can customize your own puzzle embed:&lt;/p&gt;
&lt;script&gt;
document.addEventListener(&#39;alpine:init&#39;, () =&gt; {
  Alpine.data(&#39;puzzleConfigurator&#39;, () =&gt; ({
    imageUrl: &#39;https://images.unsplash.com/photo-1682687220063-4742bd7fd538?q=80&amp;w=1000&#39;,
    bgColor: &#39;ffffff&#39;,
    pieces: 16,
    width: 600,
    height: 400,
    getIframeCode() {
      return `&lt;iframe
  src=\&#34;https://jigsaw.ishan.page?img=${this.imageUrl}&amp;bg=${this.bgColor}&amp;pieces=${this.pieces}\&#34;
  width=\&#34;${this.width}\&#34;
  height=\&#34;${this.height}\&#34;
  frameborder=\&#34;0\&#34;&gt;&lt;/iframe&gt;`;
    }
  }))
})
&lt;/script&gt;
&lt;style&gt;
input, textarea {
  font-family: monospace !important;
  display: block;
  background-color: var(--pre-background-color);
  color: var(--pre-text-color);
  width: 100%;
}

button {
  background: var(--accent-color);
  box-shadow: var(--shadow-l2);
  border-radius: var(--tag-border-radius);
  padding: 8px 20px;
  color: var(--accent-color-text);
  font-size: 1.4rem;
  transition: all .3s ease;
  border: 0;
  cursor: pointer;
}

button:hover {
  background: var(--accent-color-darker);
}

.reset-button {
  padding: 4px 8px;
  font-size: 0.9rem;
}

.flex-row {
  display: flex;
  flex-direction: row;
  gap: 15px;
  margin-bottom: 20px;
}

.flex-col {
  display: flex;
  flex-direction: column;
}

.col-50 {
  flex: 1 1 50%;
}

.col-25 {
  flex: 1 1 25%;
}

.col-75 {
  flex: 1 1 75%;
}

.color-preview {
  display: inline-block;
  width: 20px;
  height: 20px;
  vertical-align: middle;
  margin-left: 5px;
}

details {
  margin-bottom: 20px;
}

summary {
  cursor: pointer;
  font-weight: bold;
  margin-bottom: 10px;
}

input[type=&#34;range&#34;] {
  width: 100%;
}

input[type=&#34;number&#34;], input[type=&#34;text&#34;] {
  width: 100%;
}
&lt;/style&gt;
&lt;div x-data=&#34;puzzleConfigurator&#34;&gt;
&lt;div class=&#34;flex-col&#34; style=&#34;margin-bottom: 20px;&#34;&gt;
&lt;label for=&#34;imageUrl&#34;&gt;Image URL:&lt;/label&gt;
&lt;input type=&#34;text&#34; id=&#34;imageUrl&#34; x-model=&#34;imageUrl&#34;&gt;
&lt;/div&gt;
&lt;div class=&#34;flex-row&#34;&gt;
&lt;div class=&#34;flex-col col-25&#34;&gt;
&lt;label for=&#34;bgColor&#34;&gt;Background Color:&lt;/label&gt;
&lt;div style=&#34;display: flex; align-items: center;&#34;&gt;
&lt;input type=&#34;text&#34; id=&#34;bgColor&#34; x-model=&#34;bgColor&#34;&gt;
&lt;span class=&#34;color-preview&#34; x-bind:style=&#34;&#39;background-color: #&#39; + bgColor + &#39;;&#39;&#34;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;flex-col col-75&#34;&gt;
&lt;label for=&#34;pieces&#34;&gt;Number of Pieces: &lt;span x-text=&#34;pieces&#34;&gt;&lt;/span&gt;&lt;/label&gt;
&lt;input type=&#34;range&#34; id=&#34;pieces&#34; x-model.number=&#34;pieces&#34; min=&#34;4&#34; max=&#34;100&#34; step=&#34;1&#34;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;flex-row&#34;&gt;
&lt;div class=&#34;flex-col col-50&#34;&gt;
&lt;label for=&#34;width&#34;&gt;Width (px):&lt;/label&gt;
&lt;div style=&#34;display: flex; align-items: center; gap: 10px;&#34;&gt;
&lt;input type=&#34;number&#34; id=&#34;width&#34; x-model.number=&#34;width&#34; min=&#34;200&#34; max=&#34;1200&#34;&gt;
&lt;button @click=&#34;width = 600&#34; class=&#34;reset-button&#34;&gt;Reset&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;flex-col col-50&#34;&gt;
&lt;label for=&#34;height&#34;&gt;Height (px):&lt;/label&gt;
&lt;div style=&#34;display: flex; align-items: center; gap: 10px;&#34;&gt;
&lt;input type=&#34;number&#34; id=&#34;height&#34; x-model.number=&#34;height&#34; min=&#34;200&#34; max=&#34;1200&#34;&gt;
&lt;button @click=&#34;height = 400&#34; class=&#34;reset-button&#34;&gt;Reset&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;margin-bottom: 20px;&#34;&gt;
&lt;span x-text=&#34;&#39;Current aspect ratio: &#39; + (width/height).toFixed(2)&#34; style=&#34;font-style: italic;&#34;&gt;&lt;/span&gt;
&lt;button @click=&#34;width = 600; height = 400&#34; style=&#34;margin-left: 10px;&#34; class=&#34;reset-button&#34;&gt;Reset Dimensions&lt;/button&gt;
&lt;/div&gt;
&lt;details&gt;
&lt;summary&gt;Your Embed Code&lt;/summary&gt;
&lt;textarea x-text=&#34;getIframeCode()&#34; style=&#34;height: 100px;&#34; readonly&gt;&lt;/textarea&gt;
&lt;/details&gt;
&lt;button @click=&#34;navigator.clipboard.writeText(getIframeCode())&#34; style=&#34;margin-top: 10px;&#34;&gt;Copy to Clipboard&lt;/button&gt;
&lt;div style=&#34;margin-bottom: 20px;&#34;&gt;
&lt;h4&gt;Preview:&lt;/h4&gt;
&lt;div x-html=&#34;getIframeCode()&#34; style=&#34;width: 100%;&#34;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;credits&#34;&gt;Credits&lt;/h2&gt;
&lt;p&gt;This is essentially Dillo&amp;rsquo;s jigsaw puzzle (&lt;a class=&#34;link&#34; href=&#34;https://codepen.io/Dillo/pen/QWKLYab&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://codepen.io/Dillo/pen/QWKLYab&lt;/a&gt;) with very minor adaptations to make it work as an embed. I just added the iframe functionality and message event.&lt;/p&gt;
&lt;p&gt;The puzzle is hosted at &lt;a class=&#34;link&#34; href=&#34;https://jigsaw.ishan.page&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://jigsaw.ishan.page&lt;/a&gt; if you want to check it out.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Announcing a new chess bot - A0lite-js</title>
        <link>https://ishan.page/blog/a0lite-js/</link>
        <pubDate>Sat, 21 Dec 2024 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/a0lite-js/</guid>
        <description>&lt;p&gt;I&amp;rsquo;m excited to share a project I&amp;rsquo;ve been working on - a TypeScript port of the a0lite chess engine. The original a0lite was created as a minimalist neural network chess engine, designed to be simple and easy to understand rather than maximize playing strength.&lt;/p&gt;
&lt;p&gt;You can play against the engine by sending it a challenge &lt;a class=&#34;link&#34; href=&#34;https://lichess.org/?user=A0Lite-JS#friend&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;. Please note that the bot can only play 3 simultaneous challenges at a time. It accepts bullet, blitz, and rapid challenges, casual or rated.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://lichess.org/@/A0lite-js/perf/bullet&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://lichess-shield.vercel.app/api?username=A0lite-js&amp;amp;format=bullet&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;lichess-rapid&#34;
	
	
&gt;&lt;/a&gt;
&lt;a class=&#34;link&#34; href=&#34;https://lichess.org/@/A0lite-js/perf/blitz&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://lichess-shield.vercel.app/api?username=A0lite-js&amp;amp;format=blitz&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;lichess-rapid&#34;
	
	
&gt;&lt;/a&gt;
&lt;a class=&#34;link&#34; href=&#34;https://lichess.org/@/A0lite-js/perf/rapid&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://lichess-shield.vercel.app/api?username=A0lite-js&amp;amp;format=rapid&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;lichess-rapid&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;what-was-a0lite&#34;&gt;What was a0lite?&lt;/h2&gt;
&lt;p&gt;The original &lt;a class=&#34;link&#34; href=&#34;https://github.com/dkappe/a0lite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;dkappe/a0lite&lt;/a&gt; project was a Python implementation of a basic neural MCTS chess engine in just 95 lines of code. Unlike Leela Chess Zero (LC0) which is a full Alpha Zero clone with thousands of lines of C++ code, a0lite took a much simpler approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Single-threaded MCTS/UCT search&lt;/li&gt;
&lt;li&gt;No complex pruning or tree reuse optimizations&lt;/li&gt;
&lt;li&gt;Minimal, readable implementation focused on the core concepts&lt;/li&gt;
&lt;li&gt;Designed for experimentation and learning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While the original project has been inactive since November 2020, it provided an excellent foundation for understanding neural network chess engines without the complexity of production systems.&lt;/p&gt;
&lt;h2 id=&#34;why-typescript&#34;&gt;Why TypeScript?&lt;/h2&gt;
&lt;p&gt;While there is an Emscripten port of LC0 that can run in browsers, it has significant limitations and performance issues. By reimplementing the core concepts in TypeScript, we can create an engine that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runs natively in modern browsers without emulation overhead&lt;/li&gt;
&lt;li&gt;Takes advantage of WebAssembly and Web Workers for better performance&lt;/li&gt;
&lt;li&gt;Has a smaller footprint and faster load times&lt;/li&gt;
&lt;li&gt;Integrates smoothly with web technologies and frameworks&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-is-a0lite-js&#34;&gt;What is a0lite-js?&lt;/h2&gt;
&lt;p&gt;a0lite-js is a TypeScript implementation that builds on the original a0lite&amp;rsquo;s philosophy of simplicity while adding features needed for practical use. It&amp;rsquo;s designed to work with LC0 neural networks that have been converted to the ONNX format, making them usable in JavaScript/TypeScript environments.&lt;/p&gt;
&lt;p&gt;The engine implements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UCI (Universal Chess Interface) protocol for compatibility with chess GUIs&lt;/li&gt;
&lt;li&gt;Monte Carlo Tree Search (MCTS) with UCT for position evaluation&lt;/li&gt;
&lt;li&gt;Neural network inference using ONNX Runtime&lt;/li&gt;
&lt;li&gt;Support for both standard chess positions and custom FEN positions&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;current-limitations&#34;&gt;Current Limitations&lt;/h2&gt;
&lt;p&gt;While the engine plays reasonably well in many positions, it has some significant weaknesses:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mate Blindness&lt;/strong&gt;: The engine sometimes misses obvious checkmates, even when they&amp;rsquo;re just a few moves away. This is partly due to the MCTS implementation not specifically prioritizing mate-seeking lines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Draw Tendencies&lt;/strong&gt;: A major issue is the engine&amp;rsquo;s propensity to fall into threefold repetition in winning positions. Even with a clear advantage, it may choose moves that allow the opponent to force a draw through repetition. This behavior stems from:
&lt;ul&gt;
&lt;li&gt;Insufficient exploration of alternative winning lines&lt;/li&gt;
&lt;li&gt;Lack of proper draw-avoidance heuristics in the search&lt;/li&gt;
&lt;li&gt;The neural network&amp;rsquo;s training data possibly including too many drawn games&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time Management&lt;/strong&gt;: The current time management system is basic and can lead to suboptimal move choices under time pressure.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;future-development&#34;&gt;Future Development&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m actively working on addressing these limitations. Key areas of focus include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implementing mate detection in the search&lt;/li&gt;
&lt;li&gt;Adding draw-avoidance heuristics&lt;/li&gt;
&lt;li&gt;Improving time management&lt;/li&gt;
&lt;li&gt;Optimizing the MCTS implementation for browser environments&lt;/li&gt;
&lt;li&gt;Supporting more UCI options&lt;/li&gt;
&lt;li&gt;Exploring WebAssembly for performance-critical components&lt;/li&gt;
&lt;li&gt;Adding Web Worker support for background processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal is to create a strong, web-native chess engine that maintains strategic understanding while addressing tactical weaknesses.&lt;/p&gt;
&lt;h2 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;You can play against the engine by sending it a challenge &lt;a class=&#34;link&#34; href=&#34;https://lichess.org/?user=A0Lite-JS#friend&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To try out a0lite-js on your own computer, you will need to have git, bun and lc0 already installed. After that, do the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Clone the repository and install dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/sad-pixel/a0lite-js.git
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; a0lite-js
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Convert your LC0 network to ONNX format using:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lc0 leela2onnx --input&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&amp;lt;path-to-network-file&amp;gt; --output&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;lc0.onnx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Place the resulting ONNX model in the &lt;code&gt;nets&lt;/code&gt; directory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the engine using Bun:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run index.ts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will start a0lite-js as a UCI chess engine that can be used with any UCI-compatible chess GUI. The engine can also be integrated directly into web applications.&lt;/p&gt;
&lt;p&gt;You can play against the engine by sending it a challenge &lt;a class=&#34;link&#34; href=&#34;https://lichess.org/?user=A0Lite-JS#friend&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;. Please note that the bot can only handle 3 challenges at the same time.&lt;/p&gt;
&lt;h2 id=&#34;contributing&#34;&gt;Contributing&lt;/h2&gt;
&lt;p&gt;Contributions are welcome! Feel free to open issues or submit pull requests on GitHub. In particular, help with addressing the mate detection and draw-avoidance issues would be greatly appreciated.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Send Applescript Notifications from your CLI easily with this nifty alias</title>
        <link>https://ishan.page/blog/macos-notify-cli/</link>
        <pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/macos-notify-cli/</guid>
        <description>&lt;p&gt;Have you ever wanted to send desktop notifications from your command line on macOS?&lt;/p&gt;
&lt;p&gt;This can be particularly useful when you want to be notified when a long-running process completes. For example, you could append &lt;code&gt;; notify &amp;quot;Task completed!&amp;quot;&lt;/code&gt; to any command.&lt;/p&gt;
&lt;p&gt;While there are several ways to do this, I find using AppleScript through the &lt;code&gt;osascript&lt;/code&gt; command to be the simplest approach. Here&amp;rsquo;s a handy shell function that lets you send notifications with just a single command.&lt;/p&gt;
&lt;p&gt;To use this notification function, you&amp;rsquo;ll need to add it to your shell&amp;rsquo;s configuration file. If you&amp;rsquo;re using zsh (the default shell on modern macOS), add the following function to your &lt;code&gt;~/.zshrc&lt;/code&gt; file. If you&amp;rsquo;re using bash, add it to your &lt;code&gt;~/.bashrc&lt;/code&gt; instead.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;notify&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;:-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;Notification&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt; -z &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$message&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Usage: notify &amp;lt;message&amp;gt; [title]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  osascript -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;display notification \&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$message&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;\&amp;#34; with title \&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$title&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;\&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;p&gt;With a custom title:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;notify &lt;span class=&#34;s2&#34;&gt;&amp;#34;hello world!&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Custom Title&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Without a custom title:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;notify &lt;span class=&#34;s2&#34;&gt;&amp;#34;hello world!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        </item>
        <item>
        <title>Why FileLinks Didn&#39;t Work in Google Colab</title>
        <link>https://ishan.page/blog/colab-download-files/</link>
        <pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/colab-download-files/</guid>
        <description>&lt;p&gt;If you&amp;rsquo;ve ever worked on a project in Google Colab and tried to provide download links for files using &lt;code&gt;FileLink&lt;/code&gt;, you might have encountered some issues. Specifically, you might have noticed that the links often point to &lt;code&gt;localhost:8080&lt;/code&gt;, making them useless for actual downloads. This can be frustrating, especially when you just want a simple way for users to download files generated by your notebook.&lt;/p&gt;
&lt;p&gt;So, why does this happen, and what can you do about it?&lt;/p&gt;
&lt;h2 id=&#34;the-problem-with-filelink-in-google-colab&#34;&gt;The Problem with &lt;code&gt;FileLink&lt;/code&gt; in Google Colab&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;FileLink&lt;/code&gt; is a handy feature in Jupyter Notebooks that creates a hyperlink to a file stored in your notebook&amp;rsquo;s environment. However, Google Colab runs your notebooks on remote servers, not on your local machine. When you use &lt;code&gt;FileLink&lt;/code&gt; in Colab, the generated link points to &lt;code&gt;localhost:8080&lt;/code&gt;, which is your local machine&amp;rsquo;s loopback address. This doesn&amp;rsquo;t make sense in a remote server context because your local machine has no idea where the Colab server is.&lt;/p&gt;
&lt;p&gt;In simpler terms, &lt;code&gt;FileLink&lt;/code&gt; is trying to give you a shortcut to a place it can&amp;rsquo;t actually reach. This results in broken links that won&amp;rsquo;t help you or your users download the files they need.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of code that doesn&amp;rsquo;t work well in Google Colab:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;IPython.display&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FileLink&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Sample DataFrame to save as CSV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DataFrame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Column1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Column2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sample_results.csv&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Creating a FileLink&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FileLink&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;When you run this code in Google Colab, the link it generates points to &lt;code&gt;localhost:8080&lt;/code&gt;, which is not accessible from the Colab environment, making it impossible to download the file.&lt;/p&gt;
&lt;h2 id=&#34;the-button-based-solution&#34;&gt;The Button-Based Solution&lt;/h2&gt;
&lt;p&gt;Instead of relying on &lt;code&gt;FileLink&lt;/code&gt;, which doesn&amp;rsquo;t work well in Google Colab, we can use buttons that trigger file downloads. Google Colab has built-in support for this through the &lt;code&gt;google.colab&lt;/code&gt; library, making it easy to create buttons for downloading files.&lt;/p&gt;
&lt;p&gt;To implement this, you can use widgets from &lt;code&gt;ipywidgets&lt;/code&gt; to create buttons and attach functions to handle the downloads. Here&amp;rsquo;s a simple way to do it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ipywidgets&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;widgets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;IPython.display&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;google.colab&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Sample DataFrame to save as CSV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DataFrame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Column1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Column2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sample_results.csv&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Function to display download buttons&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;display_download_buttons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;result_button&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;widgets&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Download Results&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;download_result_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;files&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;download&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;result_button&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;on_click&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;download_result_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_button&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Call the function to display the download button&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;display_download_buttons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_file_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This code snippet demonstrates how to create a simple button that allows users to download a CSV file generated in the notebook.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re working in Google Colab and need a reliable way for users to download files, avoid &lt;code&gt;FileLink&lt;/code&gt; and go for a button-based solution with &lt;code&gt;colab.files&lt;/code&gt;. This not only solves the problem of broken links but also enhances the user experience by providing a straightforward and effective way to download files. Happy coding!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>When Using `bc`, `scale` Doesn&#39;t Round!</title>
        <link>https://ishan.page/blog/bc-rounding-scale/</link>
        <pubDate>Wed, 06 Mar 2024 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/bc-rounding-scale/</guid>
        <description>&lt;p&gt;Ever stumbled upon a  weird problem and couldn&amp;rsquo;t quite figure out where things went wrong?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been there, and so has a friend of mine while tackling a HackerRank challenge.&lt;/p&gt;
&lt;p&gt;The task seemed simple: take a mathematical expression as input and print out the result with three decimal places.&lt;/p&gt;
&lt;p&gt;However, getting there wasn&amp;rsquo;t as straightforward as expected.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s walk through what happened and how we can apply the lessons learned to similar problems.&lt;/p&gt;
&lt;h2 id=&#34;the-initial-problem&#34;&gt;The Initial Problem&lt;/h2&gt;
&lt;p&gt;The challenge required reading an expression from the input and then outputting the result to three decimal places. My friend&amp;rsquo;s first attempt looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt; var
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$((&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;scale=3; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$var&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; bc&lt;span class=&#34;k&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;However, one test case failed due to being off by 0.001. This tiny discrepancy was a significant clue that the approach to handling decimal precision and rounding needed reevaluation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side Note&lt;/strong&gt;&lt;br&gt;
Although this is a personal style preference, the usual way I would pipe a string into &lt;code&gt;bc&lt;/code&gt; would involve echoing the string or using a heredoc, not directly using the &lt;code&gt;$(())&lt;/code&gt; syntax.&lt;/p&gt;
&lt;p&gt;A better version might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt; var
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;scale=3; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$var&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;I suggested increasing the &lt;code&gt;scale&lt;/code&gt; to 4 (&lt;code&gt;scale=4&lt;/code&gt;) to explore the behavior, which led to failing all test cases. It seemed counterintuitive, but the point was to dig deeper into how the &lt;code&gt;bc&lt;/code&gt; command processes numbers.&lt;/p&gt;
&lt;h2 id=&#34;what-we-discovered&#34;&gt;What We Discovered&lt;/h2&gt;
&lt;p&gt;After running some tests locally (always a good practice before submitting your solution), we noticed something interesting:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$input&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5+50*3/20 + &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;19*2&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;/7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;scale=4; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$input&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;17.9285
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;scale=3; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$input&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;17.928
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$input&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$input&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bc -l
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;17.92857142857142857142
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;printf&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%.3f\n&amp;#34;&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$input&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bc -l&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;17.929
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The exploration revealed a crucial detail: &lt;code&gt;bc&lt;/code&gt; truncates rather than rounds numbers when applying the &lt;code&gt;scale&lt;/code&gt;. That&amp;rsquo;s where the &lt;code&gt;printf&lt;/code&gt; function becomes handy.&lt;/p&gt;
&lt;h2 id=&#34;the-practical-solution&#34;&gt;The Practical Solution&lt;/h2&gt;
&lt;p&gt;The workaround is to use &lt;code&gt;bc -l&lt;/code&gt; for the calculation to ensure full precision and then &lt;code&gt;printf &amp;quot;%.3f\n&amp;quot;&lt;/code&gt; to format the output correctly, rounding to three decimal places.&lt;/p&gt;
&lt;h2 id=&#34;key-takeaways&#34;&gt;Key Takeaways&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Precision Matters&lt;/strong&gt;: The failure of a test case by just 0.001 should immediately signal that the handling of decimal precision and rounding is critical.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test Locally&lt;/strong&gt;: Always run your code locally first (unless it&amp;rsquo;s impossible of course!). It helps catch errors and understand the problem better.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Know Your Tools&lt;/strong&gt;: Understanding how commands like &lt;code&gt;bc&lt;/code&gt; and &lt;code&gt;printf&lt;/code&gt; work is crucial. &lt;code&gt;bc&lt;/code&gt; sets the number of decimal places but doesn&amp;rsquo;t round, while &lt;code&gt;printf&lt;/code&gt; can format and round the output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Experiment and Learn&lt;/strong&gt;: Don&amp;rsquo;t be afraid to change your approach. Testing with a &lt;code&gt;scale&lt;/code&gt; of 4 revealed how &lt;code&gt;bc&lt;/code&gt; handles precision.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pay Attention to Details&lt;/strong&gt;: Small discrepancies can point to larger issues. A mismatch of 0.001 isn&amp;rsquo;t just a minor error; it&amp;rsquo;s an indicator that your method of handling precision needs adjustment.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you face a coding challenge, keep these insights in mind.&lt;/p&gt;
&lt;p&gt;Sometimes, the solution involves more than just writing the code; it&amp;rsquo;s about understanding the behavior of the tools at your disposal.&lt;/p&gt;
&lt;p&gt;Happy coding! Have you ever faced a similiar problem before? &lt;a class=&#34;link&#34; href=&#34;mailto:hello@ishan.page&#34; &gt;Tell me all about it!&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Read This Next: Using AI For Recommending Posts On My Blog</title>
        <link>https://ishan.page/blog/read-this-next-embeddings-llm-rag/</link>
        <pubDate>Sun, 03 Mar 2024 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/read-this-next-embeddings-llm-rag/</guid>
        <description>&lt;img src="https://ishan.page/blog/read-this-next-embeddings-llm-rag/signs.jpg" alt="Featured image of post Read This Next: Using AI For Recommending Posts On My Blog" /&gt;&lt;blockquote&gt;
&lt;p&gt;Featured Photo by &lt;a href=&#34;https://unsplash.com/@soymeraki?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash&#34;&gt;Javier Allegue Barros&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Imagine landing on a blog where every &amp;ldquo;Read This Next&amp;rdquo; suggestion feels like it was handpicked just for you.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the kind of reading journey I want for you on my blog.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been experimenting, trying to develop a system that not only understands the content of my posts but also why they might resonate with you, the reader. This feature is &lt;strong&gt;now live&lt;/strong&gt;, and I&amp;rsquo;m going to explore the process.&lt;/p&gt;
&lt;h2 id=&#34;why-move-beyond-traditional-recommendation-systems&#34;&gt;Why Move Beyond Traditional Recommendation Systems?&lt;/h2&gt;
&lt;p&gt;Hugo has a pretty good, very configurable keyword and category based recommendation system. With careful selection and tweaking of weights, I&amp;rsquo;ve been able to have it recommend stuff to my liking so far.&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s not what I wanted.&lt;/p&gt;
&lt;p&gt;Have you ever finished an article on AI ethics only to be recommended a generic post on &amp;ldquo;Top 10 AI Innovations&amp;rdquo;? It&amp;rsquo;s informative, sure, but it misses the mark on continuing the nuanced conversation you were engaged in.&lt;/p&gt;
&lt;p&gt;I wanted to dig deeper. I wanted to create a recommendation that felt almost like a friend was suggesting what you should read next- Related, but also having a wide range of topics.&lt;/p&gt;
&lt;p&gt;This required a system capable of understanding content at a near-human level and making connections between seemingly disparate topics based on underlying themes and ideas.&lt;/p&gt;
&lt;h2 id=&#34;rag-text-embeddings-and-gpt-4&#34;&gt;RAG, Text Embeddings and GPT-4&lt;/h2&gt;
&lt;p&gt;To bridge this gap, I turned to AI, specifically text embeddings and GPT-4. I used LangChain to make interacting with the tools easier, though in future posts I will explore further on using the core modules directly.&lt;/p&gt;
&lt;p&gt;Text embeddings allow us to transform written content into numerical vectors, representing the essence of a post in a form that computers can understand and compare. It&amp;rsquo;s like capturing the soul of an article in numbers. GPT-4, on the other hand, offers an advanced understanding of language, capable of generating summaries, and even explaining why one article relates to another in a human-like manner.&lt;/p&gt;
&lt;p&gt;For instance, an article on the ethical considerations of AI could lead you to a seemingly unrelated post on philosophy, connected by the underlying theme of ethics and technology.&lt;/p&gt;
&lt;p&gt;This is an application of the well known RAG (Retrieval Augmented Generation) pattern.&lt;/p&gt;
&lt;h2 id=&#34;summarizing-posts&#34;&gt;Summarizing Posts&lt;/h2&gt;
&lt;p&gt;The process starts off when a summary is generated for each blog post using LangChain and OpenAI&amp;rsquo;s GPT-4 model.&lt;/p&gt;
&lt;p&gt;The script employs a &lt;a class=&#34;link&#34; href=&#34;https://harikirankante.hashnode.dev/how-to-summarize-large-documents-using-langchain-and-openai-in-python&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;map-reduce approach&lt;/a&gt; where each document (part of a blog post) is first summarized individually (map step), and then these section wise summaries are further condensed (reduce step).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.chains&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LLMChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MapReduceDocumentsChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              &lt;span class=&#34;n&#34;&gt;ReduceDocumentsChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.chains.combine_documents.stuff&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StuffDocumentsChain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.prompts&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PromptTemplate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.text_splitter&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TokenTextSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_community.document_loaders&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UnstructuredMarkdownLoader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_openai.chat_models&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatOpenAI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;map_template&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Write a concise summary of the following content:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{content}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Summary:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;map_prompt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PromptTemplate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatOpenAI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gpt-4-turbo-preview&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;map_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LLMChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prompt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map_prompt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;reduce_template&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;The following is set of summaries:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{doc_summaries}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Summarize the above summaries with all the key details
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Summary:&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;reduce_prompt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PromptTemplate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reduce_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;reduce_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LLMChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prompt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reduce_prompt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;stuff_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StuffDocumentsChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;llm_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reduce_chain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;document_variable_name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;doc_summaries&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;reduce_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ReduceDocumentsChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;combine_documents_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stuff_chain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;map_reduce_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MapReduceDocumentsChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;llm_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map_chain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;document_variable_name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;reduce_documents_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reduce_chain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;post&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;./post/name-of-post/index.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;loader&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UnstructuredMarkdownLoader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;post&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;loader&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;splitter&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TokenTextSplitter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chunk_size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;split_docs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;splitter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;map_reduce_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invoke&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split_docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;output_text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;embedding-and-storing&#34;&gt;Embedding and Storing&lt;/h2&gt;
&lt;p&gt;The generated summaries are then processed through a text embedding model. This converts the summaries into a high-dimensional space where similar contents are positioned closer together, facilitating the comparison of thematic and semantic similarities between posts.&lt;/p&gt;
&lt;p&gt;These embeddings are stored in ChromaDB, a vector database optimized for fast similarity searches.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.embeddings&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CacheBackedEmbeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.storage&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LocalFileStore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Chroma&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_core.documents&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_openai&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OpenAIEmbeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loads&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sum.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;underlying_embeddings&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;text-embedding-3-large&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;store&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LocalFileStore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;./cache/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cached_embedder&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CacheBackedEmbeddings&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_bytes_store&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;underlying_embeddings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;store&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;namespace&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;underlying_embeddings&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sum_source&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sum_page&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;doc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page_content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sum_page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;metadata&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;source&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum_source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Chroma&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_documents&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cached_embedder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;finding-related-posts&#34;&gt;Finding Related Posts&lt;/h2&gt;
&lt;p&gt;To find similar posts, we query ChromaDB with the embedding of the current post, retrieving other posts with the closest embeddings. This step uses Maximal Marginal Relevance, an algorithm that considers both similarity and diversity, making sure that recommendations are both relevant and varied.&lt;/p&gt;
&lt;p&gt;For each recommended post, GPT-4 is used to generate an engaging, brief explanation of why it might be of interest, based on the thematic connections identified through the embeddings.&lt;/p&gt;
&lt;p&gt;This step adds a personal touch to the recommendations, making them feel more curated and thoughtful.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;collections&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.chains&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LLMChain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain.prompts&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PromptTemplate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;langchain_openai&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatOpenAI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;relateds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;rec_template&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;You are an intelligent AI-powered content recommendation assistant. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Here&amp;#39;s a summary of the article that the reader has just read:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{summary_a}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Here&amp;#39;s a summary of the next article recommended for the reader:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{summary_b}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Now, write why the reader might find it interesting based on the contents of both the articles. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Don&amp;#39;t say things like &amp;#34;Given&amp;#34;, &amp;#34;Dive in&amp;#34;, &amp;#34;Elevate&amp;#34; etc.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Always start with a attention grabbing, relevant and catchy hook.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Your answer should explain in no more than one sentence using clear, concise, conversational language.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Don&amp;#39;t be superfluous, use superlatives or exaggerate. Always be practical. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;Always refer to the reader as &amp;#34;you&amp;#34; and the author in the first person.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ChatOpenAI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gpt-4-turbo-preview&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;temperature&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;rec_prompt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PromptTemplate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rec_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;rec_chain&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LLMChain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prompt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rec_prompt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;llm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;For: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sum_source&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sum_page&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;found_docs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_marginal_relevance_search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sum_page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fetch_k&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summaries&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;$ne&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum_source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;doc&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;enumerate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;found_docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rec_chain&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invoke&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;summary_a&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum_page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;summary_b&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page_content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;relateds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;post/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;doc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;metadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;why&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;relateds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting It All Together&lt;/h2&gt;
&lt;p&gt;Finally, now that I have the list of related posts, I&amp;rsquo;m going to put them in a &lt;code&gt;next.json&lt;/code&gt; content file next to each post&amp;rsquo;s &lt;code&gt;index.md&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;read_next&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;post/2023-07-09-programming-with-the-grain&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;why&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;You might dig the next article because it switches gears from the nifty math trick you just explored to the practical world of programming, showing you how to ride the wave of a language&amp;#39;s inherent features for smoother coding. It&amp;#39;s like applying a smart formula but in the realm of coding, making your work not just correct but elegantly efficient.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;post/2023-06-20-facebook-graph-leads-between&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;why&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;The reader, having just explored a mathematical trick for estimating digits in powers of 2, might find the next article intriguing as it shifts focus from theoretical math to practical application, demonstrating how to leverage Python and the Facebook Graph API for data retrieval tasks. This presents an opportunity to see Python&amp;#39;s versatility in action, from performing mathematical computations to interacting with web APIs.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;slug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;post/2021-09-18-pem-linux&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;why&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;If you enjoyed learning a neat mathematical trick for estimating digits in powers of two, you might find diving into the practical world of cryptography with RSA key generation equally fascinating. It&amp;#39;s a cool way to see how mathematical concepts can be applied to enhance security in computing tasks like setting up secure, passwordless connections.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Finally, I create a shortcode to display the recommendations inside the post in &lt;code&gt;layouts/shortcodes/read-next.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ $dataFile := &amp;#34;next.json&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ range .Page.Resources.Match $dataFile }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ $data := .Content | transform.Unmarshal }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Read Next
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;I&amp;#39;m running [an experiment](/blog/read-this-next-embeddings-llm-rag/) for better content recommendations. These are the 3 posts that are most likely to be interesting for you:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ range $data.read_next }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ $page := site.GetPage .slug }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ if $page }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- [{{ $page.Title }}]({{ $page.RelPermalink }})  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    {{ .why | markdownify }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ else }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{/* Handle the case where the page is not found */}}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ printf &amp;#34;Recommended reading not found for slug or filename: &amp;#39;%s&amp;#39;&amp;#34; .slug }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And here&amp;rsquo;s the result:&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/&#34; &gt;Blogging with Jupyter Notebooks in Hugo&lt;/a&gt;&lt;br&gt;
Exploring how I embraced Jupyter notebooks for blogging could spark your curiosity about integrating cutting-edge tools into your own content creation process, just like the AI-driven recommendations system aims to revolutionize blog engagement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-04-addendum-webfinger/&#34; &gt;Addendum: What&#39;s a Webfinger?&lt;/a&gt;&lt;br&gt;
Explore how Webfinger’s API can streamline your blog’s user experience by effortlessly connecting readers with authors’ profiles, mirroring the personalized content recommendations you just read about.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
Unlock the power of Python for your projects by learning how to fetch data from Facebook Lead Ads, a skill that complements the AI-driven content recommendation techniques you just explored.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Calculating The Number Of Digits In A Power Of 2</title>
        <link>https://ishan.page/blog/power-digits-log-formula-trick/</link>
        <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/power-digits-log-formula-trick/</guid>
        <description>&lt;p&gt;I want to share something cool I learned about logarithms. If you&amp;rsquo;ve found logarithms a bit tricky, like I did, you&amp;rsquo;ll love this trick!&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a neat way to see logarithms in action and made things click for me.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Someone asked me how I would go about approximating the number of digits in $2^{32}$.&lt;/p&gt;
&lt;p&gt;I found &lt;a class=&#34;link&#34; href=&#34;https://math.stackexchange.com/questions/1693073/how-many-digits-are-in-the-integer-representation-of-2-to-the-30th-power&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this discussion&lt;/a&gt; on StackExchange. To quote the top answer:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A general formula for the number of digits of any power of 2 can be found using the value of the base-10 logarithm of 2.&lt;/p&gt;
&lt;p&gt;The number of digits in $2^k$ is&lt;br&gt;
$1 + \lfloor k \cdot \log_{10}(2) \rfloor$&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The trick uses a fundamental property of logarithms and shows how they relate to the scale of numbers in different bases, particularly base 10 (since we&amp;rsquo;re interested in the number of digits). Let&amp;rsquo;s try to break it down:&lt;/p&gt;
&lt;p&gt;The logarithm of a number is the exponent to which another fixed number, the base, must be raised to produce that number.&lt;/p&gt;
&lt;p&gt;In this case, we&amp;rsquo;re dealing with $log_{10}$, which tells us how many times we must multiply 10 to get our number.&lt;/p&gt;
&lt;p&gt;Given $2^k$, where $k$ is an integer, we want to find out how many digits this number has.&lt;/p&gt;
&lt;p&gt;To do this, we can take the base 10 logarithm of $2^k$, expressed as $\log_{10}(2^k)$.&lt;/p&gt;
&lt;p&gt;Using the property of logarithms that allows us to bring the exponent to the front, we get:&lt;/p&gt;
&lt;p&gt;$\log_{10}(2^k) = k \cdot \log_{10}(2)$&lt;/p&gt;
&lt;p&gt;The value of $\log_{10}(2)$ is approximately $0.30$. This tells us how many times 10 must be multiplied to reach the base 2.&lt;/p&gt;
&lt;p&gt;When we multiply this value by $k$, we get a sense of how large $2^k$ is in terms of its place in the base-10 system.&lt;/p&gt;
&lt;p&gt;The resulting value $k \cdot \log_{10}(2)$ gives us a decimal number that correlates with the magnitude of $2^k$ in base 10.&lt;/p&gt;
&lt;p&gt;However, this doesn&amp;rsquo;t directly tell us the number of digits. We still need to floor it and add 1.&lt;/p&gt;
&lt;p&gt;The logarithm gives us the &amp;ldquo;order of magnitude&amp;rdquo; of our number in base 10.&lt;/p&gt;
&lt;p&gt;For example, $\log_{10}(100) = 2$, meaning $10^2 = 100$ has 3 digits.&lt;/p&gt;
&lt;p&gt;The log tells us it&amp;rsquo;s in the hundreds place, but we know that anything in the hundreds (from 100 to 999) has 3 digits.&lt;/p&gt;
&lt;p&gt;By adding 1 to the result, we essentially round up from this &amp;ldquo;order of magnitude&amp;rdquo; to the actual number of digits.&lt;/p&gt;
&lt;p&gt;We have to take the floor because the result isn&amp;rsquo;t always clean.&lt;/p&gt;
&lt;p&gt;Consider the cases of 553 and 999:&lt;/p&gt;
&lt;p&gt;$\log_{10}(553) = 2.472$ &lt;br&gt;
$\lfloor\log_{10}(553)\rfloor = 2$ &lt;br&gt;
$\lfloor\log_{10}(553)\rfloor + 1 = 3$&lt;/p&gt;
&lt;p&gt;$\log_{10}(999) = 2.999$&lt;br&gt;
$\lfloor\log_{10}(999)\rfloor = 2$ &lt;br&gt;
$\lfloor\log_{10}(999)\rfloor + 1 = 3$&lt;/p&gt;
&lt;p&gt;This works because the number of digits is always one more than its logarithm&amp;rsquo;s floor value for numbers in base 10.&lt;/p&gt;
&lt;p&gt;The formula $(1 + k \cdot \log_{10}(2))$ therefore calculates the number of digits in $2^k$ by using the log to find its order of magnitude in base 10, and then adjusting for the fact that the number of digits is one more than that magnitude.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to verify the result:&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll calculate the number of digits in two ways using a Python script, with the first method being the formula, and the other by converting $2^k$ to a string and getting its length. Finally we&amp;rsquo;ll compare the results and note the differences.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;math&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;math&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;floor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;math&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;log10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;501&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;mismatches&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mismatches&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# []&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This verification code loops over $k$ from 1 to 500. Since there is nothing in the mismatches array, it shows that the formula $1 + \lfloor k \cdot \log_{10}(2) \rfloor$ correctly gives the number of digits in $2^k$ for every value of $k$ in this range.&lt;/p&gt;
&lt;p&gt;The trick isn&amp;rsquo;t limited just to powers of 2 - you can use any number in the log.&lt;/p&gt;
&lt;p&gt;Therefore, a more general formula for finding the number of digits in $x^k$ would be:&lt;br&gt;
$1 + \lfloor k \cdot \log_{10}(x) \rfloor$&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/&#34; &gt;Programming &amp;quot;with the grain&amp;quot;&lt;/a&gt;&lt;br&gt;
Unlocking the secrets of efficient coding, this article takes you from the mathematical elegance of estimating digits in powers of two to mastering the art of programming in harmony with the underlying logic of computer systems and languages, enhancing both your problem-solving skills and code quality.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
Unlock the power of Python further by learning how to harness Facebook’s vast data through its Graph API, a skill that complements your mathematical prowess with practical, real-world application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-09-18-pem-linux/&#34; &gt;Generate PEM file for any Linux user&lt;/a&gt;&lt;br&gt;
Unlock the power of secure, passwordless connections by learning how to create a 4096-bit RSA key pair, a perfect next step after mastering the mathematical elegance of estimating digits in powers of two.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Blogging with Jupyter Notebooks in Hugo</title>
        <link>https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/</link>
        <pubDate>Fri, 15 Dec 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/</guid>
        <description>&lt;img src="https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/hugo_jupyter.png" alt="Featured image of post Blogging with Jupyter Notebooks in Hugo" /&gt;&lt;blockquote&gt;
&lt;p&gt;Featured Photo by &lt;a class=&#34;link&#34; href=&#34;https://www.pexels.com/photo/silhouette-of-mountains-1323550/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Simon Berger&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve realized something important about myself lately: I need to make it easy for me to publish my stuff.  If I have to do a lot of steps to get my text online, I lose motivation and give up. That&amp;rsquo;s why I switched from my custom PHP site to a hugo site with a ready-made theme on Cloudflare pages. Now I just have to &lt;code&gt;git push&lt;/code&gt; and it&amp;rsquo;s done.&lt;/p&gt;
&lt;p&gt;I used to hate working with Jupyter notebooks because they required me to open a browser and deal with all the hassle of web interfaces. But ever since VS Code added support for &lt;code&gt;.ipynb&lt;/code&gt; files, I&amp;rsquo;ve changed my mind.&lt;/p&gt;
&lt;p&gt;Now I can easily play around with code and data, and see the results in real time. It&amp;rsquo;s great for learning new things.&lt;/p&gt;
&lt;p&gt;One cool feature of Jupyter notebooks is that they can have markdown cells, where you can write text with formatting. That got me thinking: what if I could use Jupyter notebooks to write blog posts and then render them in hugo? That would be awesome, right?&lt;/p&gt;
&lt;p&gt;I present to you:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{ % ipynb &amp;#34;simple.ipynb&amp;#34; % }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The rest of this post is written in the Jupyter notebook.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/simple.ipynb&#34; download&gt;🗒️ Download (simple.ipynb)&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;this-is-a-jupyter-notebook&#34;&gt;This Is A Jupyter Notebook&lt;/h2&gt;
&lt;p&gt;It has a markdown starting section, that&amp;rsquo;s quite neat!&lt;br&gt;
Let&amp;rsquo;s try to create a Python code block next:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Alright, that seems to have gone well! Note how this second section is sandwiched in the middle of two code blocks.&lt;/p&gt;
&lt;p&gt;The next code block uses &lt;code&gt;print&lt;/code&gt; to send the output. The reason for this will be important later!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;This is a message!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;This is a message!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;thinking-about-options&#34;&gt;Thinking about Options&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take a moment and evaluate:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hugo &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/content-management/page-resources/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Page Resources&lt;/a&gt; can be used to attach a resource to a post&lt;/li&gt;
&lt;li&gt;A Jupyter Notebook is actually just a JSON file.&lt;/li&gt;
&lt;li&gt;Cursory googling shows people trying various options, including rendering:
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://pypi.org/project/hugo_jupyter/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;hugo_jupyter&lt;/a&gt; - Turns &amp;ldquo;notebook&amp;rdquo; into it&amp;rsquo;s own type of post. Frontmatter goes inside notebooks&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/vlunot/nb2hugo&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;nb2hugo&lt;/a&gt; - Similiar approach as above&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.hugoblox.com/tutorial/blog/step-4/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Blox&lt;/a&gt; - Some custom themes take the same approach above&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://discourse.gohugo.io/t/ipython-notebook-support/3211&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Forum Topic discussing Jupyter Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://skeptric.com/jupyter-hugo-blog/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Skeptric on the nb2hugo workflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;looking-inside-notebooks&#34;&gt;Looking Inside Notebooks&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take a look inside &lt;strong&gt;this&lt;/strong&gt; notebook itself. Since it&amp;rsquo;s a JSON file, we can use &lt;code&gt;jq&lt;/code&gt; and the &lt;code&gt;keys&lt;/code&gt; function to start exploring:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jq&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;M&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;keys&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;simple&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipynb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;cells&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;metadata&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;nbformat&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;nbformat_minor&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Remember how I mentioned that the fact I used &lt;code&gt;print&lt;/code&gt; will be relevant later? It&amp;rsquo;s coming soon. I promise. Let&amp;rsquo;s take a look at the first 4 cells of the notebook:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jq&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;M&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;.cells[:4]&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;simple&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipynb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-mysql&#34; data-lang=&#34;mysql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;attachments&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cell_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;markdown&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;## This Is An Example Jupyter Notebook\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;It has a markdown starting section, that&amp;#39;s quite neat!   \n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Let&amp;#39;s try to create a Python code block next:&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cell_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;execution_count&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;26&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;outputs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;text/plain&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;execution_count&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;26&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;output_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;execute_result&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2 + 2&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;attachments&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cell_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;markdown&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Alright, that seems to have gone well! Note how this second section is sandwiched in the middle of two code blocks.\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;The next code block uses `print` to send the output. The reason for this will be important later!&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cell_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;execution_count&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;27&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;outputs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;output_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;stream&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;This is a message!\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;print(\&amp;#34;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;This&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;is&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Observations&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every object has a &lt;code&gt;cell_type&lt;/code&gt; which is either &lt;code&gt;markdown&lt;/code&gt; or &lt;code&gt;code&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;All cells have a &lt;code&gt;source&lt;/code&gt;. Source is as array of strings containing the cell&amp;rsquo;s source code line by line.&lt;/li&gt;
&lt;li&gt;Cells which have been executed have an &lt;code&gt;outputs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;While &lt;code&gt;outputs&lt;/code&gt; is always an array, the contents differ:
&lt;ul&gt;
&lt;li&gt;When it&amp;rsquo;s a normal Python evaluation, the &lt;code&gt;output_type&lt;/code&gt; is &lt;code&gt;execution_result&lt;/code&gt;.&lt;br&gt;
In this case, we have to get the data from the &lt;code&gt;outputs[].data&lt;/code&gt; which is a object containing keys corresponding to the mime type and value as an array containing the values.&lt;/li&gt;
&lt;li&gt;When it&amp;rsquo;s using &lt;code&gt;print&lt;/code&gt;, the &lt;code&gt;output_type&lt;/code&gt; is &lt;code&gt;stream&lt;/code&gt;.&lt;br&gt;
In this case, the &lt;code&gt;outputs[].text&lt;/code&gt; is the array of strings we are interested in.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;but-what-about-images&#34;&gt;But What About Images?&lt;/h2&gt;
&lt;p&gt;Fair point! We haven&amp;rsquo;t encountered any in this notebook yet. Let&amp;rsquo;s change that by copying in one of the &lt;a class=&#34;link&#34; href=&#34;https://matplotlib.org/stable/gallery/lines_bars_and_markers/bar_colors.html#sphx-glr-gallery-lines-bars-and-markers-bar-colors-py&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;matplotlib examples&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;plt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subplots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fruits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;blueberry&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;cherry&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;counts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;40&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;55&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;bar_labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;_red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;bar_colors&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;tab:red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;tab:blue&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;tab:red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;tab:orange&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fruits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;counts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bar_labels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bar_colors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_ylabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;fruit supply&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Fruit supply by kind and color&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;legend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Fruit color&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;img src=&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYUAAAEICAYAAACwDehOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAiQUlEQVR4nO3deZxU5Z3v8c8XUNEAKtoiigg6LmyChsUog7hhElFhBI2iQjB6iVFD5mpeZKKJmpsbJ2NWt2iigsQYlBBwnEzGDEq8qCNCVMAgYpJW0JZNRVBBlt/945w&amp;#43;qW6qu6uX6mro7/v1qled5TnP&amp;#43;Z2nq8&amp;#43;vzlLnUURgZmYG0KbUAZiZWcvhpGBmZhknBTMzyzgpmJlZxknBzMwyTgpmZpZxUrBGkzRO0hOljqM2knpICkntGrDsPElfKmYMkrpL2iSpbQPrLpd0RmNjLGA9wyWtaul1WsM5KbRi6Y7k43RnVPk6pL71RMRDETEip96Q9A9NG&amp;#43;3uLSLejIgOEbG91LFY6&amp;#43;akYOekO6PK19u5MxvyzdqsuTT0yMpq5qRgO0m/6X9F0gpgRb7THrmnVCRNkDQ/HX46LfJyeuRxYZ76/0HSHyVtkLRO0ox0eiHreUbS7emyr0o6vVrZ70lakM6fI6lznvWPlbSo2rT/LWl2Lc1yZL56Jf2HpGuq1bVY0qha6qosd356tNa3&amp;#43;ran2/KddHs3SnpC0oE5y14q6Q1J6yV9s471nC3pRUkfSFop6aaceZXrHS/pzfTv8c2c&amp;#43;XtLmirpPUl/BgbVsa4&amp;#43;kv4g6V1JqyX9Szp9L0k/lvR2&amp;#43;vqxpL1qqKNXuv3vS3pF0rk586ZKulvS7yR9CJxaayNbvTkpWE1GAUOA3vVZKCKGpYP90yOPGXmKfQd4Atgf6AbcXo9VDAH&amp;#43;ChwIfBuYVW3HfxkwETgE2Ab8NE8djwE9JfXKmXYJML2W9dZU77R0WQAk9QcOBX5X20ZI&amp;#43;iLwr8AZEbG0hmIXA18EDgL2BK5Ll&amp;#43;0N3A1cmsZzAEk71uTDNP79gLOBL&amp;#43;dJWkOBY4DTgW/ltM23gSPT11nA&amp;#43;Fq2qSPw38Dv07j&amp;#43;AZibzv4mcCIwAOgPDAZuyFPHHsC/k3w&amp;#43;DgKuAR6SdExOsYuB7wIdgfm1bLc1gJOCzU6/kb1f7Zvy9yLi3Yj4uAjr3AocDhwSEZsjoj7/2GuAH0fE1jThLCfZ0VWaHhFLI&amp;#43;JD4EbgguqnGCJiCzCDdGcuqQ/QA3i8lvXWVO8c4ChJR6XlLgVmRMQntdQ1GbgeGB4Rr9dS7oGIeC39GzxCskMFGAM8HhFPp9tyI7CjpkoiYl5ELImIHRGxGHgYOKVasZsj4uOIeBl4mWTHDXAB8N30s7CS/Em20kjgnYj4Qfp33RgRz6fzxgG3RMSaiFgL3EzSVtWdCHQAbo2ITyLiSZK/y0U5ZeZExDPp9myuJR5rACcFGxUR&amp;#43;6WvUTnTVxZxnV8HBCxITw9MrMeyb0XVpzi&amp;#43;QfKttNLKavP2IDmqqG4acLEkkeycHkl3sDXJW2&amp;#43;6zCPAJZLakOy8ajvigCQh3BkRdd1x807O8EckO0tItjeLJ01U62uqRNIQSU9JWitpAzCJndukoHWRbHtNDgP&amp;#43;UsO8Q6otW/3vlltuZUTsqFb20JzxYn42Wz0nBatJ7o73w/R9n5xpBze44oh3IuKKiDgE&amp;#43;F/AXUruVipkPYemO/JK3YHci&amp;#43;OHVZu3FViXJ4b/AT4B/pHkdERdO/La6p1G8k34dOCjiHiujrpGADdIOr&amp;#43;OcjWpyI1H0j4kp5Bq8iuSU2aHRcS&amp;#43;wM9IknK910Wy7TVZSXKaKZ&amp;#43;3SY4Oc&amp;#43;t5u4Zyh6UJNrfsWznjfrRzETkpWJ3Sw/23SL4Nt02/2df0zw&amp;#43;wGjiippnphd7Kc&amp;#43;DvkfyTby9wPQcB10raQ9JYoBdVz99fIql3uqO8BZhZy22eDwJ3ANsKOIVVY71pEtgB/IC6kwvAK8BngTtzL6LWw0xgpKShkvZM46ntf7kj8G5EbJY0mCQJFuoR4BuS9k//ZtfUUvZx4GBJk9MLyx0lDUnnPUySCMvSC&amp;#43;bfAn6Zp47nSb4cfD39Gw8HzgF&amp;#43;XY&amp;#43;YrRGcFKxQV5Cc9lgP9AGeraXsTcC09DrFBXnmDwKel7SJ5BvsVyPibwWu53ngKJJv6d8FxkRE7qmT6cBUktMh7YFra4lzOtCXwnbkddX7INCP/Du6naTn7kcCP5f0uUKWyVn2FeArJEcAFSSJtbZTUVcBt0jaSLIzfqQeq7uZ5PTN30gu/tbYVhGxETiTZCf&amp;#43;DrCCv98d9H&amp;#43;AhcBiYAnwp3Ra9To&amp;#43;Ac4FPkfyN74LuCwiXq1HzNYIcic7tquQNAH4UkQMrWH&amp;#43;POCXEfGLAuvbm&amp;#43;TC9QkRsaKRsV0GXFlTbGa7Ch8pWGv2ZeCFJkgI&amp;#43;5B8G7&amp;#43;3SaIyKyH/WtVaJUnlJBdbRzWynrOAWST35/&amp;#43;q0YGZlZhPH5mZWcanj8zMLLNLnz468MADo0ePHqUOw8xsl7Jo0aJ1EVGWb94unRR69OjBwoULSx2GmdkuRVKNv0z36SMzM8s4KZiZWcZJwczMMrv0NQWzYti6dSurVq1i82Y/ldl2be3bt6dbt27sscceBS/jpGBWzapVq&amp;#43;jYsSM9evSg6gNZzXYdEcH69etZtWoVPXv2LHg5nz4yq2bz5s0ccMABTgi2S5PEAQccUO8j3qIlBUn3S1ojaWnOtM5p/60r0vf9c&amp;#43;Z9Q9Lrkpanjw4wKxknBNsdNORzXMwjhakkz4zPNQWYGxFHkfTdOgWyPme/QPKo5M&amp;#43;SdLrSFjMza1ZFSwoR8TTwbrXJ55H0UkX6Pipn&amp;#43;q8jYkv6XP3XSTr2NrMSadu2LQMGDMhe5eXlBS/7s5/9jAcffBCAqVOn8vbb&amp;#43;TpZq5/y8nL69u3b6Hqsds19oblLRFQARESFpIPS6YcC/5NTbhVV&amp;#43;2TNSLoSuBKge/faega0Yusx5T9KHUJR/Pzcrmxd9X6d5Y7rtl/RYymlvffem5deeinvvIggImjTJv/3ykmTJmXDU6dOpW/fvhxySL4umYtn27ZttGvne2nqq6VcaM534ivv41sj4t6IGBgRA8vK8j66w8yKoLy8nF69enHVVVdxwgknsHLlSjp06JDNnzlzJhMmTADgpptu4rbbbmPmzJksXLiQcePGMWDAAD7&amp;#43;&amp;#43;OMqdb7&amp;#43;&amp;#43;uucccYZ9O/fnxNOOIG//OUvRATXX389ffv2pV&amp;#43;/fsyYMWOnWDZv3swXv/hF&amp;#43;vXrx/HHH89TTz0FJAlo7NixnHPOOYwYMaJ4jbEba&amp;#43;40ulpS1/QooStJr1eQHBnkdg7ejfydeptZM/n4448ZMGAAAD179uRHP/oRy5cv54EHHuCuu&amp;#43;4qqI4xY8Zwxx13cNtttzFw4MCd5o8bN44pU6YwevRoNm/ezI4dO5g1axYvvfQSL7/8MuvWrWPQoEEMGzasynJ33nknAEuWLOHVV19lxIgRvPbaawA899xzLF68mM6dOzdi61uv5j5SeAwYnw6PB&amp;#43;bkTP9C2tl3T5I&amp;#43;eBc0c2xmlqPy9NFLL73Eb3/7WwAOP/xwTjzxxCapf&amp;#43;PGjbz11luMHj0aSH5otc8&amp;#43;&amp;#43;zB//nwuuugi2rZtS5cuXTjllFN44YUXqiw7f/58Lr30UgCOPfZYDj/88CwpnHnmmU4IjVC0IwVJDwPDgQMlrQK&amp;#43;DdwKPCLpcuBNYCwkHZFLegT4M7AN&amp;#43;EpEbC9WbGbWMJ/61KeqjOfe8ljf&amp;#43;&amp;#43;Fr6uCrkI6/aitTPUarn2LefXRRRHSNiD0ioltE3BcR6yPi9Ig4Kn1/N6f8dyPiyIg4JiL&amp;#43;s1hxmVnT6dKlC8uWLWPHjh3Z0UR1HTt2ZOPGjTtN79SpE926dWP27NkAbNmyhY8&amp;#43;&amp;#43;ohhw4YxY8YMtm/fztq1a3n66acZPLjqzYjDhg3joYceAuC1117jzTff5JhjjmnajWulWsqFZjPbBd16662MHDmS0047ja5du&amp;#43;YtM2HCBCZNmpT3QvP06dP56U9/ynHHHcdJJ53EO&amp;#43;&amp;#43;8w&amp;#43;jRoznuuOPo378/p512Gt///vc5&amp;#43;OCDqyx31VVXsX37dvr168eFF17I1KlT2WuvvYq2na3JLt1H88CBA8Od7JTO7nxLapfuR9RZbne/JdV2D8uWLaNXr15VpklaFBE7X/nHRwpmZpbDScHMzDJOCmZmlnFSMDOzjJOCmZllnBTMzCzjRwia1WGPMz6Td/qyBtbX69WGLmlWfD5SMGthysvL2XvvvbOH0QH06NGjUXVOmDCBmTNnAjB8&amp;#43;PA6&amp;#43;0aYMGEC8&amp;#43;bNy9a9bt26ncpUPgm1IcrLyxk&amp;#43;fHid5Rq73fk0pi1akty4xo0bR&amp;#43;fOnbPtagwnBbMW6Mgjj6yxL4NK27f78WCVWlJblCKWhx56iHPPPbdJ6nJSMNsFVPYdMm/ePE499VQuvvhi&amp;#43;vXrx/bt27n&amp;#43;&amp;#43;usZNGgQxx13HPfccw&amp;#43;QPDDu6quvpnfv3px99tmsWbMmq6tz5860bVt7b7f77rsve&amp;#43;65Zzb&amp;#43;b//2bwwePJjBgwfz&amp;#43;uuv71R&amp;#43;&amp;#43;PDhVD5dYN26ddk3/Jria9u2bUFPMq2tz5RStMXcuXM5/vjj6devHxMnTmTLli1AckRzyy23MHToUB599FF&amp;#43;/vOfM2jQIPr378/555/PRx99BCTf7q&amp;#43;99lpOOukkjjjiiOyb/Y4dO7jqqqvo06cPI0eO5POf/3w2b9GiRZxyyil8&amp;#43;tOf5qyzzqKiomKnuJqSrymY7QJyHx29YMECli5dSs&amp;#43;ePbn33nvZd999eeGFF9iyZQsnn3wyI0aM4MUXX2T58uUsWbKE1atX07t3byZOnAjArFmz6lzfT37ykyrjnTp1YsGCBTz44INMnjyZxx9/vKC477vvvrzx9ezZs6A4qj8yu7rmbIvNmzczYcIE5s6dy9FHH81ll13G3XffzeTJk4Hk0d/z588HYP369VxxxRUA3HDDDdx3331cc801AFRUVDB//nxeffVVzj33XMaMGcOsWbMoLy9nyZIlrFmzhl69ejFx4kS2bt3KNddcw5w5cygrK2PGjBl885vf5P7779/pb9RUnBTMdjGDBw&amp;#43;mZ8&amp;#43;eADzxxBMsXrw4&amp;#43;1a5YcMGVqxYwdNPP531SXDIIYdw2mmnNWqdF110Ufb&amp;#43;ta99reDlaoqvMv7Gas62WL58OT179uToo48GYPz48dx5551ZUrjwwguzskuXLuWGG27g/fffZ9OmTZx11lnZvFGjRtGmTRt69&amp;#43;7N6tWrgaR/iLFjx9KmTRsOPvhgTj311GydS5cu5cwzzwSSI6&amp;#43;aHjzYVJwUzHYxuf0FRAS33357lZ0OwO9&amp;#43;97sqfR00Vm5d&amp;#43;ept164dO3bsAKr2q1BTfE2lOduiroeH5sYyYcIEZs&amp;#43;eTf/&amp;#43;/Zk6dWqVC9W5T3OtrLO2viX69OnDc88914jI68fXFMzqsPW/n8v76vXqsga9mtJZZ53F3XffzdatW4Gkb4EPP/yQYcOG8etf/5rt27dTUVGR9WFc3WWXXcaCBXV3cljZT/KMGTP4zGd2vkW3R48eLFq0CKDKHTA1xZfrrbfe4vTTTy9ga2tX7LY49thjKS8vz66pTJ8&amp;#43;nVNOOSVv2Y0bN9K1a1e2bt2a9ftQm6FDh/Kb3/yGHTt2sHr16iyJHHPMMaxduzZLClu3buWVV16ps77G8JGC2S7sS1/6EuXl5ZxwwglEBGVlZcyePZvRo0fz5JNP0q9fP44&amp;#43;&amp;#43;ugad16LFy8u6HTEli1bGDJkCDt27ODhhx/eaf51113HBRdcwPTp06ucnqkpvlwVFRW0a9f4XVGx26J9&amp;#43;/Y88MADjB07lm3btjFo0CAmTZqUt&amp;#43;x3vvMdhgwZwuGHH06/fv3ydjKU6/zzz2fu3Ln07duXo48&amp;#43;miFDhmQXkmfOnMm1117Lhg0b2LZtG5MnT6ZPnz6FN0w9uT8FazD3p7BfUdZfXl7OyJEjWbp0aVHqr/TBBx9w&amp;#43;eWX8&amp;#43;ijjxZ1PXW544476N69e5PdUtkQLaEtNm3aRIcOHVi/fj2DBw/mmWee2alzodpMmDCBkSNHMmbMmCrT69ufgo8UzFqYtm3bsmHDBgYMGFDnbxUao1OnTiVPCABXX311qUNoEW0xcuRI3n//fT755BNuvPHGeiWEcePG8eyzz&amp;#43;6UEBrCScGshTnssMNYuXJlqcNoMZYsWcKll15aZdpee&amp;#43;3F888/X6KIiqMxv5ou5LpFoZwUzKoJgoho0rt3rOH69etX1COm3VlDLg/47iOzat54fyvbPvqgQf9QZi1FRLB&amp;#43;/Xrat29fr&amp;#43;V8pGBWze3Pv8c1wOH7rUPUfLSwbOPezReUWQO0b9&amp;#43;ebt261WsZJwWzaj7YsoPvPr2&amp;#43;znLlt57dDNGYNS&amp;#43;fPjIzs4yTgpmZZZwUzMws46RgZmYZJwUzM8s4KZiZWcZJwczMMk4KZmaWKUlSkPQ1Sa9IWirpYUntJXWW9AdJK9L3/UsRm5lZa9bsSUHSocC1wMCI6Au0Bb4ATAHmRsRRwNx03MzMmlGpTh&amp;#43;1A/aW1A7YB3gbOA&amp;#43;Yls6fBowqTWhmZq1XsyeFiHgLuA14E6gANkTEE0CXiKhIy1QAB&amp;#43;VbXtKVkhZKWrh27drmCtvMrFUoxemj/UmOCnoChwCfknRJoctHxL0RMTAiBpaVlRUrTDOzVqkUp4/OAP4WEWsjYiswCzgJWC2pK0D6vqYEsZmZtWqlSApvAidK2kdJ11anA8uAx4DxaZnxwJwSxGZm1qo1e38KEfG8pJnAn4BtwIvAvUAH4BFJl5MkjrHNHZuZWWtXkk52IuLbwLerTd5CctRgZmYl4l80m5lZxknBzMwyTgpmZpZxUjAzs4yTgpmZZZwUzMws46RgZmYZJwUzM8s4KZiZWcZJwczMMk4KZmaWcVIwM7OMk4KZmWWcFMzMLOOkYGZmGScFMzPLOCmYmVnGScHMzDJOCmZmlnFSMDOzjJOCmZllnBTMzCzjpGBmZhknBTMzy9SZFCRdLWn/5gjGzMxKq5AjhYOBFyQ9IumzklTsoMzMrDTqTAoRcQNwFHAfMAFYIen/SjqyyLGZmVkzK&amp;#43;iaQkQE8E762gbsD8yU9P0ixmZmZs2sXV0FJF0LjAfWAb8Aro&amp;#43;IrZLaACuArxc3RDMzay51JgXgQOCfIuKN3IkRsUPSyOKEZWZmpVBjUpDUOR38cbVxACLi3YhYVrzQzMysudV2pLAIiHS4&amp;#43;h1HARxRlIjMzKxkakwKEdGzWCuVtB/J9Ym&amp;#43;JAlmIrAcmAH0AMqBCyLivWLFYGZmOyvo7iNJ/yTph5J&amp;#43;IGlUE6z3J8DvI&amp;#43;JYoD&amp;#43;wDJgCzI2Io4C56biZmTWjQn7RfBcwCVgCLAUmSbqzoSuU1AkYRvK7ByLik4h4HzgPmJYWmwaMaug6zMysYQq5&amp;#43;&amp;#43;gUoG/6WwUkTSNJEA11BLAWeEBSf5JrF18FukREBUBEVEg6qBHrMDOzBijk9NFyoHvO&amp;#43;GHA4kassx1wAnB3RBwPfEg9ThVJulLSQkkL165d24gwzMysukKSwgHAMknzJM0D/gyUSXpM0mMNWOcqYFVEPJ&amp;#43;OzyRJEqsldQVI39fkWzgi7o2IgRExsKysrAGrNzOzmhRy&amp;#43;uhbTbnCiHhH0kpJx0TEcuB0kkTzZ5JfTt&amp;#43;avs9pyvWamVnd6kwKEfFHSQcDg0luH30hIt5p5HqvAR6StCfwV&amp;#43;CLJEctj0i6HHgTGNvIdZiZWT0V8uyjL5EcLTxJ8iO22yXdEhH3N3SlEfESMDDPrNMbWqeZmTVeIaePrgeOj4j1AJIOAJ4FGpwUzMysZSrkQvMqYGPO&amp;#43;EZgZXHCMTOzUirkSOEt4HlJc0iuKZwHLJD0zwAR8cMixmdmZs2okKTwl/RVqfKuoI5NH46ZmZVSIXcf3dwcgZiZWekVcvfRU/z9EdqZiDitKBGZmRXipn1LHUFp3bShKNUWcvroupzh9sD5JP00m5nZbqaQ00eLqk16RtIfixSPmZmVUCGnj3K74WwDfBo4uGgRmZlZyRRy&amp;#43;qiyW06RnDb6G3B5MYMyM7PSKOT0UdG65TQzs5alkJ7XxkrqmA7fIGmWpBOKH5qZmTW3Qh5zcWNEbJQ0FDiLpKvMu4sblpmZlUIhSWF7&amp;#43;n42SW9pc4A9ixeSmZmVSiFJ4S1J9wAXAL&amp;#43;TtFeBy5mZ2S6mkJ37BcB/AZ&amp;#43;NiPeBziSP0zYzs91MIXcffQTMyhmvACqKGZSZmZWGTwOZmVnGScHMzDKF/E7hXwuZZmZmu75CjhTOzDPtc00diJmZlV6NF5olfRm4CjhC0uKcWR2BZ4odmJmZNb/a7j76FfCfwPeAKTnTN0bEu0WNyszMSqK2pBARUS7pK9VnSOrsxGBmtvup60hhJFUfnV0pgCOKGJeZmZVAjUkhIkam7350tplZK1FIz2vD8k2PiKebPhwzMyulQnpey33OUXtgMMkppdOKEpGZmZVMIc8&amp;#43;Oid3XNJhwPeLFpGZmZVMQx5zsQro29SBmJlZ6RVyTeF2kruNIEkiA4CXixiTmZmVSCHXFBbmDG8DHo4I/6LZzGw3VGtSkNQWODMiLmmmeMzMrIRqvaYQEduBMklN3iezpLaSXpT0eDreWdIfJK1I3/dv6nWamVntCrnQXA48I&amp;#43;lGSf9c&amp;#43;WqCdX8VWJYzPgWYGxFHAXOp&amp;#43;rwlMzNrBoUkhbeBx9OyHXNeDSapG3A28IucyecB09LhacCoxqzDzMzqr7ZHZ0&amp;#43;PiEuB9yPiJ0283h8DX6dqcumS9v9MRFRIOqiGuK4ErgTo3r17o4JYdmyvRi2/q&amp;#43;v16rK6C5lZq1LbkcKnJR0OTJS0f3rOP3s1dIWSRgJrImJRQ5aPiHsjYmBEDCwrK2toGGZmlkdtdx/9DPg9ydNQF9F0T0k9GThX0udJHpvRSdIvgdWSuqZHCV2BNQ2s38zMGqjGI4WI&amp;#43;GlE9ALuj4gjIqJnzqvBj82OiG9ERLeI6AF8AXgyveX1MWB8Wmw8MKeh6zAzs4ap80JzRHy5OQIBbgXOlLSCpF/oW5tpvWZmlirkF81FExHzgHnp8Hrg9FLGY2bW2jXkgXhmZrabclIwM7OMk4KZmWWcFMzMLOOkYGZmGScFMzPLOCmYmVnGScHMzDJOCmZmlnFSMDOzjJOCmZllnBTMzCzjpGBmZhknBTMzyzgpmJlZpqT9KZi1ZsuO7VXqEEqq16vLSh2C5eEjBTMzyzgpmJlZxknBzMwyTgpmZpZxUjAzs4yTgpmZZZwUzMws46RgZmYZJwUzM8s4KZiZWcZJwczMMk4KZmaWcVIwM7OMk4KZmWWcFMzMLOOkYGZmmWZPCpIOk/SUpGWSXpH01XR6Z0l/kLQifd&amp;#43;/uWMzM2vtSnGksA343xHRCzgR&amp;#43;Iqk3sAUYG5EHAXMTcfNzKwZNXtSiIiKiPhTOrwRWAYcCpwHTEuLTQNGNXdsZmatXUmvKUjqARwPPA90iYgKSBIHcFANy1wpaaGkhWvXrm22WM3MWoOSJQVJHYDfAJMj4oNCl4uIeyNiYEQMLCsrK16AZmatUEmSgqQ9SBLCQxExK528WlLXdH5XYE0pYjMza81KcfeRgPuAZRHxw5xZjwHj0&amp;#43;HxwJzmjs3MrLVrV4J1ngxcCiyR9FI67V&amp;#43;AW4FHJF0OvAmMLUFsZmatWrMnhYiYD6iG2ac3ZyxmZlaVf9FsZmYZJwUzM8s4KZiZWcZJwczMMk4KZmaWcVIwM7OMk4KZmWWcFMzMLOOkYGZmGScFMzPLOCmYmVnGScHMzDJOCmZmlnFSMDOzjJOCmZllnBTMzCzjpGBmZhknBTMzyzgpmJlZxknBzMwyTgpmZpZxUjAzs4yTgpmZZZwUzMws46RgZmYZJwUzM8s4KZiZWcZJwczMMk4KZmaWcVIwM7OMk4KZmWWcFMzMLOOkYGZmmRaXFCR9VtJySa9LmlLqeMzMWpMWlRQktQXuBD4H9AYuktS7tFGZmbUeLSopAIOB1yPirxHxCfBr4LwSx2Rm1mq0K3UA1RwKrMwZXwUMyS0g6UrgynR0k6TlzRRbMRwIrCvZ2qWSrbqJlLT99K&amp;#43;lWnOT8eevcUrbfjc3qv0Or2lGS0sK&amp;#43;bYyqoxE3Avc2zzhFJekhRExsNRx7Krcfo3j9muc3bX9Wtrpo1XAYTnj3YC3SxSLmVmr09KSwgvAUZJ6StoT&amp;#43;ALwWIljMjNrNVrU6aOI2CbpauC/gLbA/RHxSonDKqbd4jRYCbn9Gsft1zi7ZfspIuouZWZmrUJLO31kZmYl5KRgZmYZJ4UWRNIESXeUOo6mJKmHpKV5ps&amp;#43;T1KDb&amp;#43;STdJOm6xke3&amp;#43;5E0VdKYUsdhuy4nBWtVlGhT03hr5rb5u9a87a1yo4tB0mxJiyS9kv7qGkmbJP1A0p8kzZVUlk6fJ&amp;#43;nHkp6VtFTS4Dz1lUn6jaQX0tfJzb1NTaidpGmSFkuaKWmf3JmSNuUMj5E0NR2urQ36S3pS0gpJV&amp;#43;Qsf31adrGkm9NpPSQtk3QX8CfgH6uN3yjpRzl1XCHph8VoiKYm6bJ0W1&amp;#43;WND2dPCz9bP0196ihtbVNXST9c/r/t1TS5DxtcZikuyUtTP&amp;#43;vb85ZtlzSzen/9hJJx6bTyyT9IZ1&amp;#43;j6Q3JB2YzrtE0gJJL6Xz2pZmy&amp;#43;sQEX41wQvonL7vDSwFDiD5Nfa4dPq3gDvS4XnAz9PhYcDSdHhCTplfAUPT4e7AslJvYwPbpUfaDien4/cD16VtMDCdtimn/Bhgam1tANwEvJy29YEkj0Y5BBhBcpugSL7wPJ62bw9gB3BiTky5458C/gLskY4/C/QrddsV0LZ9gOXAgZWfQWAq8Gi6/b1JniVGa2ubAtru08CSdPs6AK8Ax&amp;#43;due2Wbpu9t08/scel4OXBNOnwV8It0&amp;#43;A7gG&amp;#43;nwZ9PP/oFAL&amp;#43;Dfc9rxLuCyUrdDvleL&amp;#43;p3CLu5aSaPT4cOAo0g&amp;#43;YDPSab8EZuWUfxggIp6W1EnSftXqOwPorb8/H6aTpI4RsbEYwRfZyoh4Jh3&amp;#43;JXBtgcvlbYN0eE5EfAx8LOkpkocpDiXZ&amp;#43;b2YlulA8nd4E3gjIv4np&amp;#43;5sPCI&amp;#43;lPQkMFLSMpJ/3CX13srmdxowMyLWAUTEu2lbzY6IHcCfJXVJy46gdbVNXYYCv42IDwEkzQL&amp;#43;kZ3b4oL0yL8d0JUk0S5O51X&amp;#43;Py8C/imn3tEAEfF7Se&amp;#43;l008nSUQvpH&amp;#43;jvYE1RdiuRnNSaAKShpPswD4TER9Jmge0z1M0ahjON94mre/jJgqzlOra1tzx3HbL2wbpP1W&amp;#43;OgR8LyLuqVa&amp;#43;B/BhtfLVx38B/AvwKvDATlvQMomd2wFgS7Uyle&amp;#43;tqW3qUtPT5LJtl9ST5Kh2UES8l57WzP18Vrbzdv6&amp;#43;L62pXgHTIuIbDY64mfiaQtPYF3gvTQjHAiem09uQnA4BuBiYn7PMhQCShgIbImJDtTqfAK6uHJE0oAhxN5fukj6TDl9E1XYAWC2pV3phb3TO9Nra4DxJ7SUdAAwneUTKfwETJXVIyx8q6aBCAoyI50mO8C4mPYrbBcwl&amp;#43;SZ7AICkzrWUbW1tU5engVGS9pH0KZLP3f&amp;#43;rVqYTSZLYkB5xfa6AeucDFwBIGgHsn06fC4ypbHNJnSXV&amp;#43;KTSUvKRQtP4PTBJ0mKSc7yVh58fAn0kLQI2kCaC1HuSniX54E3MU&amp;#43;e1wJ1pne1IPsSTihR/sS0Dxku6B1gB3A2ckzN/Csk57pUk12M6pNNra4MFwH&amp;#43;QXGv4TkS8DbwtqRfwXHo0sQm4hOSbXCEeAQZExHt1lmwBIuIVSd8F/ihpO38/NZSv7BOtqW3qEhF/Sr/5L0gn/QJ4r1qZlyW9SHK94a/AM9TtZuBhSRcCfwQqgI0RsU7SDcAT6ZefrcBXgDeaYnuakh9zUUSSNkVEhzzT5wHXRcTC5o/KaiLpceBHETG31LG0NG6bwkjaC9geyXPcPgPcHREDShxWvfhIwVq99CL/AuBl7/SqctvUW3fgkfRo4BPgijrKtzg&amp;#43;UjAzs4wvNJuZWcZJwczMMk4KZmaWcVIwM7OMk4KZmWX&amp;#43;P6OXzQXOzMrpAAAAAElFTkSuQmCC&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Figure size 432x288 with 1 Axes&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s take a look inside this last cell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jq&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;M&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;.cells[-3].outputs[].data | keys&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;simple&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipynb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;image/png&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;text/plain&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s take a look at what&amp;rsquo;s inside the image:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jq&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;M&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;.cells[-3].outputs[].data[&amp;#34;image/png&amp;#34;][:32]&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;simple&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipynb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;iVBORw0KGgoAAAANSUhEUgAAAYUAAAEI&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s a base64 encoded png! That makes our life easier.&lt;/p&gt;
&lt;p&gt;Now, with all the observations so far, we now have enough information to create the shortcode&lt;/p&gt;
&lt;h2 id=&#34;the-ipynb-shortcode&#34;&gt;The &lt;code&gt;ipynb&lt;/code&gt; Shortcode&lt;/h2&gt;
&lt;h3 id=&#34;why-a-shortcode&#34;&gt;Why a Shortcode?&lt;/h3&gt;
&lt;p&gt;Most of the previous approaches use layouts, but I have gone with a shortcode instead. Using this approach lets me keep the frontmatter in my post markdown file.&lt;/p&gt;
&lt;p&gt;The main benefit of this is that I can have multiple notebooks inside a post if I want.&lt;/p&gt;
&lt;h3 id=&#34;copy-me&#34;&gt;Copy Me!&lt;/h3&gt;
&lt;p&gt;The below code goes in &lt;code&gt;layouts/shortcodes/ipynb.html&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{ $notebook := .Get 0 }}
{{ range .Page.Resources.Match $notebook }} 
&amp;lt;a href=&amp;quot;{{.RelPermalink}}&amp;quot; download&amp;gt;🗒️ Download ({{ $notebook }})&amp;lt;/a&amp;gt;
{{ $content := .Content | transform.Unmarshal }}
{{ $cells := $content.cells }}
{{ range $cells }}
&amp;lt;!-- For Markdown Cells --&amp;gt;
{{ if eq .cell_type &amp;quot;markdown&amp;quot; }}
{{ range .source }}{{ . | safeHTML }}{{ end }}
{{ end }}

&amp;lt;!-- For Code Cells --&amp;gt;
{{ if eq .cell_type &amp;quot;code&amp;quot; }}
```python
{{ range .source }}{{ . | safeHTML }}{{ end }}
```
{{ if gt (len .outputs) 0 }}
Output:
{{ range .outputs }}
{{ if .text }}
```
{{ range .text }}{{ . | safeHTML}}{{ end }}
```
{{ end }}
{{ range $type, $data := .data }}
{{ if strings.Contains $type &amp;quot;image&amp;quot; }}&amp;lt;img src=&amp;quot;data:{{ $type }};base64,{{ $data | safeHTML }}&amp;quot;&amp;gt;{{ end }}
{{ if strings.Contains $type &amp;quot;text&amp;quot; }}
```
{{ range $data }}{{ . | safeHTML }}{{ end }}
```
{{ end }}{{ end }}{{ end }}{{ end }}{{ end }}{{ end }}{{ end }}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;how-does-it-work&#34;&gt;How does it work?&lt;/h3&gt;
&lt;p&gt;This Hugo shortcode is designed to embed a Jupyter notebook into a Hugo website by parsing and displaying its content. It processes the Jupyter notebook content, separating Markdown and Code cells, rendering them accordingly on the Hugo page. It also handles outputs generated by code cells within the notebook.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to break down how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{{ $notebook := .Get 0 }}&lt;/code&gt;: This line gets the parameter passed to the shortcode.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ range .Page.Resources.Match $notebook }}&lt;/code&gt;: This initiates a loop over the resources associated with the current page that match the provided notebook name.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;a href=&amp;quot;{{.RelPermalink}}&amp;quot; download&amp;gt;🗒️ Download ({{ $notebook }})&amp;lt;/a&amp;gt;&lt;/code&gt;: This generates a download link for the notebook file. The &lt;code&gt;.RelPermalink&lt;/code&gt; is the relative path to the notebook file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ $content := .Content | transform.Unmarshal }}&lt;/code&gt;: This extracts the content of the notebook and stores it in the &lt;code&gt;$content&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ $cells := $content.cells }}&lt;/code&gt;: This extracts the cells (sections) of the notebook and stores them in the &lt;code&gt;$cells&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ if eq .cell_type &amp;quot;markdown&amp;quot; }}&lt;/code&gt;: This checks if a cell is of type &amp;ldquo;markdown.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ range .source }}{{ . | safeHTML }}{{ end }}&lt;/code&gt;: If the cell is a markdown type, it iterates through its content and renders it as HTML using &lt;code&gt;safeHTML&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ if eq .cell_type &amp;quot;code&amp;quot; }}&lt;/code&gt;: This checks if a cell is of type &amp;ldquo;code.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;python ... &lt;/code&gt;: This wraps code cells in a Python code block for display.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ range .source }}{{ . | safeHTML }}{{ end }}&lt;/code&gt;: Renders the content of the code cell as HTML using &lt;code&gt;safeHTML&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{{ if gt (len .outputs) 0 }}&lt;/code&gt;: Checks if the code cell has any outputs.&lt;/li&gt;
&lt;li&gt;Renders outputs:
&lt;ul&gt;
&lt;li&gt;Text Outputs: Renders text outputs of the code cell.&lt;/li&gt;
&lt;li&gt;Image Outputs: Renders image outputs encoded in base64 format.&lt;/li&gt;
&lt;li&gt;Other Outputs: Handles other types of outputs (text or image) based on their data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;limitations-and-closing-thoughts&#34;&gt;Limitations and Closing Thoughts&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;While the shortcode attempts to render Markdown and Code cells, it might not cover all possible cell types or formatting nuances within a Jupyter notebook.&lt;/li&gt;
&lt;li&gt;Inline embedded images may be bad for performance as they aren&amp;rsquo;t being lazy loaded&lt;/li&gt;
&lt;li&gt;This approach skips over a lot of the extra features which Jupyter notebooks have. I couldn&amp;rsquo;t even tell you what they are because I don&amp;rsquo;t know myself!&lt;/li&gt;
&lt;li&gt;While this is perfect for my workflow, and I&amp;rsquo;m excited by how much easier it makes for me to get more posts out by removing friction, I recognize that this shortcode/approach may not be for everyone.&lt;/li&gt;
&lt;li&gt;There is &lt;a class=&#34;link&#34; href=&#34;https://ipython.org/ipython-doc/3/notebook/nbformat.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;official documentation&lt;/a&gt; for the .ipynb format, but I didn&amp;rsquo;t really look at it. Someday in the future I might have to do that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you enjoyed reading this post. Have you experienced similiar things about the importance of removing friction in your workflow? Do you have any stories of things you automated to that end? &lt;a class=&#34;link&#34; href=&#34;mailto:hello@ishan.page&#34; &gt;Tell me all about it!&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve finally started a newsletter for those who wanted to receive updates over email. &lt;br&gt;
You can subscribe below, or &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/newsletters/00001-hello-world/&#34; &gt;check out the first issue here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;form
  action=&#34;https://buttondown.email/api/emails/embed-subscribe/ishan.page&#34;
  method=&#34;post&#34;
  target=&#34;popupwindow&#34;
  onsubmit=&#34;window.open(&#39;https://buttondown.email/ishan.page&#39;, &#39;popupwindow&#39;)&#34;
  class=&#34;embeddable-buttondown-form&#34;
&gt;
  &lt;input type=&#34;email&#34; name=&#34;email&#34; class=&#34;bd-text&#34; id=&#34;bd-email&#34; placeholder=&#34;Your Email&#34;/&gt; 
  &lt;input type=&#34;text&#34; name=&#34;metadata__name&#34; class=&#34;bd-text&#34; id=&#34;name&#34; placeholder=&#34;Your Name (Optional)&#34;/&gt; 
  &lt;input type=&#34;submit&#34; value=&#34;Subscribe&#34; /&gt;
&lt;/form&gt;
&lt;hr&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Exploring unconventional tools can unlock new potentials in your projects, just like how I found creative ways to streamline my blogging workflow and how using jq for HTML generation could inspire you to think outside the box in your own tech endeavors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-hello-world/&#34; &gt;Hello World&lt;/a&gt;&lt;br&gt;
If you’re intrigued by the idea of transforming your blogging workflow with tech, the next article’s journey to revamp an online presence might spark new inspiration for your own projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;Read This Next: Using AI For Recommending Posts On My Blog&lt;/a&gt;&lt;br&gt;
Unlock the next level of your blogging journey by exploring how AI can transform the way you connect with your audience, making your content discovery as innovative as your writing process.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Hello, World!</title>
        <link>https://ishan.page/newsletters/00001-hello-world/</link>
        <pubDate>Wed, 13 Dec 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/newsletters/00001-hello-world/</guid>
        <description>&lt;h2 id=&#34;editors-note&#34;&gt;Editor&amp;rsquo;s Note&lt;/h2&gt;
&lt;p&gt;Welcome to the inaugural issue of my newsletter!&lt;/p&gt;
&lt;p&gt;Launching this newsletter has been a long time coming. While my blog has been the primary platform for sharing my thoughts and polished work, I&amp;rsquo;ve held off on creating a newsletter until now. In this space, I aim to offer you a closer look behind the scenes, sharing the journey of how certain projects and transitions came to life.&lt;/p&gt;
&lt;p&gt;For instance, the process of building the interactive jq guide was both exhilarating and challenging.&lt;/p&gt;
&lt;p&gt;One of the hurdles involved creating the jq evaluator, a puzzle solved by leveraging Aioli.js&amp;rsquo;s wasm jq distribution and innovative approaches with alpine + web components.&lt;/p&gt;
&lt;p&gt;Additionally, migrating the website to Hugo and Cloudflare Pages wasn&amp;rsquo;t without its complexities, particularly in creating custom includes.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll also be sharing a lighthearted anecdote about my accidental use of jq, where I found myself instinctively generating &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; elements using string interpolation with raw input from ls. Sometimes, a touch of unintended creativity leads to surprisingly usable solutions!&lt;/p&gt;
&lt;p&gt;I hope you enjoy this inaugural dive into the less polished yet insightful facets of my work. And as always, I appreciate your ongoing support and feedback.&lt;/p&gt;
&lt;p&gt;Warm regards,
Ishan&lt;/p&gt;
&lt;h2 id=&#34;experiments-and-anecdotes&#34;&gt;Experiments and Anecdotes&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;To a man with jq, everything looks like JSON&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In the world of programming, sometimes our tools become an extension of our thought process. Recently, I found myself unintentionally proving this notion true. While working on a quick prototyping task, I instinctively utilized jq to generate &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; elements using string interpolation with raw input from ls.&lt;/p&gt;
&lt;p&gt;The result? A copy-pastable snippet for rapid prototyping. Who knew that accidental encounters with jq could lead to unexpectedly handy solutions?&lt;/p&gt;
&lt;p&gt;Check out the full post &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;featured-blog-posts&#34;&gt;Featured Blog Posts&lt;/h2&gt;
&lt;p&gt;As this is the first issue, I thought why not highlight some of the articles I&amp;rsquo;m proudest of so far?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-02-well-known/&#34; &gt;&amp;ldquo;The secret life of .well-known&amp;rdquo;&lt;/a&gt;&lt;br&gt;
Unveiling the often-overlooked significance of the .well-known folder, this post delves into its role and history.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/&#34; &gt;&amp;ldquo;Programming &amp;lsquo;with the grain&amp;rsquo;&amp;rdquo;&lt;/a&gt;&lt;br&gt;
A perspective on programming that aligns with the natural flow of data, this post discusses the impact of following this &amp;lsquo;grain.&amp;rsquo; Exploring how this approach enhances program efficiency, it sheds light on the underlying beauty of programming aligned with inherent data structures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/&#34; &gt;&amp;ldquo;The Ultimate Interactive JQ Guide&amp;rdquo;&lt;/a&gt;&lt;br&gt;
An achievement I&amp;rsquo;m particularly proud of, this comprehensive guide boasts 25 interactive examples for learning jq. It&amp;rsquo;s not just a tutorial; it&amp;rsquo;s an engaging journey into the heart of this powerful tool.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;Thank you for reading the inaugral issue, your support means the world to me!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d love to hear your thoughts on this issue.&lt;/p&gt;
&lt;p&gt;Feel free to hit reply and share your feedback, ideas, or topics you&amp;rsquo;d like to see covered in the future. Your input will help shape the upcoming editions!&lt;/p&gt;
&lt;p&gt;Until next time,&lt;/p&gt;
&lt;p&gt;Ishan&lt;/p&gt;
</description>
        </item>
        <item>
        <title>To A Man With `jq`, Everything Looks Like JSON</title>
        <link>https://ishan.page/blog/2023-12-07-jq-hammer-nails/</link>
        <pubDate>Thu, 07 Dec 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-12-07-jq-hammer-nails/</guid>
        <description>&lt;img src="https://ishan.page/blog/2023-12-07-jq-hammer-nails/hammers.jpg" alt="Featured image of post To A Man With `jq`, Everything Looks Like JSON" /&gt;&lt;blockquote&gt;
&lt;p&gt;Featured Photo by &lt;a class=&#34;link&#34; href=&#34;https://www.pexels.com/photo/tool-set-on-plank-175039/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;energepic.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve had a love-hate relationship with Bootstrap for a long time. While I love how fast it lets me get going, I absolutely hate the cookie cutter vibe of most of the stuff that I end up making with it. &lt;a class=&#34;link&#34; href=&#34;https://bootswatch.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Bootswatch&lt;/a&gt; is awesome, and I know that I &lt;em&gt;could&lt;/em&gt; customize my theme with SASS variables, but that adds a build step, which is additional complexity that I want to avoid when I am making business/CRUD applications.&lt;/p&gt;
&lt;p&gt;Back in the Bootstrap 3 days, there used to be a customizer. I&amp;rsquo;ve found ones around for Bootsrap 4 as well, but nothing that I quite liked, so I decided to built my own.&lt;/p&gt;
&lt;h2 id=&#34;the-preview-window&#34;&gt;The Preview Window&lt;/h2&gt;
&lt;p&gt;When I&amp;rsquo;m tweaking a theme, I&amp;rsquo;d like to have a preview of the theme on a page. The official Bootstrap examples are great for this. I downloaded the examples from the official website and stored them in a folder.&lt;/p&gt;
&lt;p&gt;Then I used AlpineJS to create a dropdown menu where users could select an example and it would load the file in an &lt;code&gt;iframe&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;html&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;lang&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;x-data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;{example: &amp;#39;&amp;#39;}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- In Navbar --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;select&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;x-model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;example&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/cheatsheet&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;cheatsheet&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/blog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;blog&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- In Body --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;iframe&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;x-bind:src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;example&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;iframe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- Alpine --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;//unpkg.com/alpinejs&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;defer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;IT WORKS!&lt;br&gt;
At this point, all I need to do is populate the &lt;code&gt;select&lt;/code&gt; and I&amp;rsquo;ll be good.&lt;/p&gt;
&lt;p&gt;Just one snag though - Since this was a rough prototype all in one file, I&amp;rsquo;d have to hardcode the options in. I thought about using &lt;code&gt;template&lt;/code&gt; and &lt;code&gt;x-for&lt;/code&gt;, but it felt like way too much effort.&lt;/p&gt;
&lt;p&gt;That was the moment I caught myself typing the following command into my shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ls &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jq -R -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#34;&amp;lt;option value=\&amp;#34;/examples/&amp;#34; + . + &amp;#34;/\&amp;#34;&amp;gt;&amp;#34; + . + &amp;#34;&amp;lt;/option&amp;gt;&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It gave me exactly what I wanted:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/album/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;album&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/album-rtl/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;album-rtl&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/badges/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;badges&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/blog/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;blog&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/blog-rtl/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;blog-rtl&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/examples/breadcrumbs/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;breadcrumbs&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;lt;!-- ... many more --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Copy paste it in, and my switcher works!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/customizr.png&#34;
	width=&#34;837&#34;
	height=&#34;390&#34;
	srcset=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/customizr_hu3e2213e2d2c3f41ae55a112cfb009208_20910_480x0_resize_box_3.png 480w, https://ishan.page/blog/2023-12-07-jq-hammer-nails/customizr_hu3e2213e2d2c3f41ae55a112cfb009208_20910_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;customizr switcher&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;214&#34;
		data-flex-basis=&#34;515px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;oh-dear&#34;&gt;Oh Dear..&lt;/h2&gt;
&lt;p&gt;Yes, that&amp;rsquo;s right – I used &lt;code&gt;jq&lt;/code&gt;, in a manner that might raise a few eyebrows. In hindsight, it felt like trying to hammer a nail with a wrench – a bit unconventional, to say the least.&lt;/p&gt;
&lt;p&gt;Breaking down this command, &lt;code&gt;ls&lt;/code&gt; is listing the files and directories, and the output is piped (&lt;code&gt;|&lt;/code&gt;) to &lt;code&gt;jq&lt;/code&gt;. The &lt;code&gt;-R&lt;/code&gt; and &lt;code&gt;-r&lt;/code&gt; flags are employed to input and output raw strings without JSON formatting. Inside the jq command, there&amp;rsquo;s an attempt to generate HTML &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; elements by string manipulation.&lt;/p&gt;
&lt;p&gt;This quirky misuse of &lt;code&gt;jq&lt;/code&gt; in a scenario where a more traditional tool like &lt;code&gt;awk&lt;/code&gt; would have been a more fitting choice was both amusing and insightful. After I was done guffawing at what I had just done, I reflected on what just happened. It was a humorous reminder of how our coding environment can shape our thought processes.&lt;/p&gt;
&lt;p&gt;As the saying goes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To a man with a hammer (jq), everything looks like a nail (JSON).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;immersion-and-learning&#34;&gt;Immersion and Learning&lt;/h2&gt;
&lt;p&gt;I love learning by immersion. It&amp;rsquo;s the best way for me to learn anything.&lt;/p&gt;
&lt;p&gt;When I immerse myself in a new topic, language, or skill, I feel like I&amp;rsquo;m absorbing it faster and deeper than any other method.&lt;/p&gt;
&lt;p&gt;I enjoy the challenge of figuring things out on my own. I also like the feeling of being part of a community that shares my interest and passion.&lt;/p&gt;
&lt;p&gt;Learning by immersion is fun, rewarding, and effective for me.&lt;/p&gt;
&lt;h2 id=&#34;side-effects-of-immersion&#34;&gt;Side-effects of Immersion&lt;/h2&gt;
&lt;p&gt;I was so obsessed with &lt;code&gt;jq&lt;/code&gt; that I didn&amp;rsquo;t even realize I was using it for everything, like fitting a square peg through a round hole.&lt;/p&gt;
&lt;p&gt;It started when I decided to write &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/&#34; &gt;the ultimate interactive guide for jq&lt;/a&gt;, I wanted to cover every aspect of it, from the basics to the advanced features.&lt;/p&gt;
&lt;p&gt;I spent hours and hours reading the documentation, experimenting with different filters, and testing various scenarios. The article languished for months because I wanted it to be perfect.&lt;/p&gt;
&lt;p&gt;I learned a lot, but I also got hooked. I started to use &lt;code&gt;jq&lt;/code&gt; for every task that involved JSON, even when it was not necessary or optimal. I just loved how &lt;code&gt;jq&lt;/code&gt; made it easy and fun to work with JSON.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jq&lt;/code&gt; is a great tool, but it is not the only tool. I had become too attached to &lt;code&gt;jq&lt;/code&gt;, and I had lost sight of the bigger picture. I needed to take a step back and reevaluate my choices. That&amp;rsquo;s how I ended up using &lt;code&gt;jq&lt;/code&gt; because I had been so caught up with immersing myself.&lt;/p&gt;
&lt;h2 id=&#34;the-struggle-to-keep-an-open-mind&#34;&gt;The Struggle To Keep An Open Mind&lt;/h2&gt;
&lt;p&gt;Sometimes I wonder if I&amp;rsquo;m too attached to my own way of thinking.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easy to fall into the trap of applying the same solution to every problem, or seeing the world through a narrow lens. But I don&amp;rsquo;t want to be that kind of person.&lt;/p&gt;
&lt;p&gt;I want to keep an open mind and learn from different perspectives. I want to challenge myself and grow as a human being. That&amp;rsquo;s why I try to expose myself to new ideas and experiences, even if they make me uncomfortable or confused at first.&lt;/p&gt;
&lt;p&gt;I think that&amp;rsquo;s the only way to avoid becoming stagnant and rigid in my mindset.&lt;/p&gt;
&lt;h2 id=&#34;awk-is-scary&#34;&gt;Awk is Scary&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t know about you, but I will confess that I find &lt;code&gt;awk&lt;/code&gt; kind of scary.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a powerful tool for text processing, but it has a weird syntax and a lot of quirks.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m usually just copy-pasting the one-liners from StackOverflow when I use &lt;code&gt;awk&lt;/code&gt;, and I&amp;rsquo;m not sure what it will do or if it will backfire.&lt;/p&gt;
&lt;p&gt;Maybe I just need more practice, but awk is not my favorite thing to use.&lt;/p&gt;
&lt;p&gt;But this &lt;em&gt;is&lt;/em&gt; where it would have been more appropriate.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ls &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;{ print &amp;#34;&amp;lt;option value=\&amp;#34;/examples/&amp;#34; $0 &amp;#34;/\&amp;#34;&amp;gt;&amp;#34; $0 &amp;#34;&amp;lt;/option&amp;gt;&amp;#34; }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This awk command constructs HTML&lt;code&gt; &amp;lt;option&amp;gt;&lt;/code&gt; elements from each line of the &lt;code&gt;ls&lt;/code&gt; output, effectively achieving the desired result with a tool more suited for text manipulation.&lt;/p&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;So, that&amp;rsquo;s how I ended up using &lt;code&gt;jq&lt;/code&gt; to generate HTML options from a list of files.&lt;/p&gt;
&lt;p&gt;It was a silly but fun moment that made me realize how much I rely on this tool for everything JSON-related.&lt;/p&gt;
&lt;p&gt;But it also reminded me that sometimes, the best tool for the job is not the one you&amp;rsquo;re most familiar with, but the one that suits the task at hand.&lt;/p&gt;
&lt;p&gt;In tech, we often face problems that require us to think outside the box and use tools in creative or unconventional ways. That&amp;rsquo;s why it&amp;rsquo;s important to have a flexible and curious mindset that allows us to learn new skills and explore different solutions.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed reading this post. Do you have any stories of using tools in unexpected ways or finding solutions in surprising places? &lt;a class=&#34;link&#34; href=&#34;mailto:hello@ishan.page&#34; &gt;Tell me all about it!&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/&#34; &gt;The Ultimate Interactive JQ Guide&lt;/a&gt;&lt;br&gt;
After exploring the creative use of jq for HTML generation, you’ll find the “Ultimate Interactive JQ Guide” a perfect next step to deepen your jq skills with hands-on examples and real-world applications.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/&#34; &gt;Blogging with Jupyter Notebooks in Hugo&lt;/a&gt;&lt;br&gt;
Exploring unconventional tools can unlock new efficiencies in your workflow, much like how I found a novel way to use jq for HTML and another author creatively integrated Jupyter notebooks into their blogging process.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/&#34; &gt;Programming &amp;quot;with the grain&amp;quot;&lt;/a&gt;&lt;br&gt;
Exploring how to bend tools to your will? The next article takes you deeper into the art of programming efficiently by aligning with the natural patterns of technology, much like using jq for HTML in unexpected ways.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Accidentally deleted your .bashrc?</title>
        <link>https://ishan.page/blog/2023-11-28-bashrc-oopsie-deleted/</link>
        <pubDate>Tue, 28 Nov 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-11-28-bashrc-oopsie-deleted/</guid>
        <description>&lt;p&gt;When beginning to use the terminal, we might accidentally delete our &lt;code&gt;.bashrc&lt;/code&gt; file.&lt;/p&gt;
&lt;h2 id=&#34;what-is-the-bashrc-file&#34;&gt;What is the .bashrc file?&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;.bashrc&lt;/code&gt; file is a configuration file used by the bash shell. It contains all the environment variables, user defined functions, aliases and other config including the prompt layout.&lt;/p&gt;
&lt;p&gt;It is a full-fledged shell script, so we can have custom commands in it as well, which runs all the commands when a new process of the shell is started.&lt;/p&gt;
&lt;h2 id=&#34;what-happens-if-i-delete-it-by-accident&#34;&gt;What happens if I delete it by accident?&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s totally possible to delete your .bashrc file by accident. If you do this, don&amp;rsquo;t panic. Your system isn&amp;rsquo;t bricked.&lt;/p&gt;
&lt;p&gt;Bash will default back to the &lt;code&gt;/etc/bash.bashrc&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;This may affect some features (such as colors, prompt, completion, etc), but the shell will still work.&lt;/p&gt;
&lt;p&gt;To see what it is like, we can call a custom session of bash with the command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bash --rcfile /etc/bash.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Deleting the &lt;code&gt;/etc/bash.bashrc&lt;/code&gt; file will make bash use the default settings from the source code. To get a simulation of that, we can run&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bash --norc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;restoring-your-config&#34;&gt;Restoring Your Config&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a special folder in *nixes called &lt;code&gt;/etc/skel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It contains all the files needed for creating a new user, and thankfully, it contains a sample &amp;ldquo;skeleton&amp;rdquo; &lt;code&gt;.bashrc&lt;/code&gt; file that we can copy into our home directory.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp /etc/skel/.bashrc ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;While there isn&amp;rsquo;t any way to get back our custom commands, we can still get a lot of stuff out &lt;strong&gt;as long as you still have a logged in session&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;declare&lt;/code&gt; built-in command in Bash is used to declare variables and give them attributes. When used with the -x option, it declares the variable as an exported variable, making it available to child processes. Exported variables are passed to any commands or scripts invoked from the current shell. However, if we run &lt;code&gt;declare -x&lt;/code&gt; by itself without giving any other parameters, it conveniently prints a list of the exported environment variables for us. The &lt;code&gt;-f&lt;/code&gt; flag works in a similiar way, but with functions&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Recover Environment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -x&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Recover Functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -f&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Recover aliases&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;alias&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;env&lt;/code&gt; command also gives us the same output, so it can be used for this purpose as well.&lt;/p&gt;
&lt;h2 id=&#34;making-and-restoring-backups&#34;&gt;Making and Restoring Backups&lt;/h2&gt;
&lt;p&gt;It may be worth taking a backup of your bashrc&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp ~/.bashrc ~/.bashrc.bkp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Restore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp ~/.bashrc.bkp ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;a-note-on-dotfile-management-with-stow&#34;&gt;A note on Dotfile Management with Stow&lt;/h2&gt;
&lt;p&gt;Stow is a symlink manager that creates symbolic links from a source directory to a target directory, avoiding conflicts and duplicates
To use git and stow for dotfile management, one possible workflow is outlined &lt;a class=&#34;link&#34; href=&#34;https://apiumhub.com/tech-blog-barcelona/managing-dotfiles-with-stow/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s okay to make mistakes. A fear of messing things up prevents us from playing around to learn. The beauty of learning is in making mistakes. I&amp;rsquo;ve deleted my &lt;code&gt;.bashrc&lt;/code&gt; file before&amp;ndash; it&amp;rsquo;s nothing to be ashamed of!&lt;/p&gt;
&lt;p&gt;Have you deleted your &lt;code&gt;.bashrc&lt;/code&gt; or other important dotfiles before? Do you already have a workflow with Stow? &lt;a class=&#34;link&#34; href=&#34;mailto:hello@ishan.page&#34; &gt;I&amp;rsquo;d love to hear about it&lt;/a&gt;!.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-21-linux-use-multiple-git-profiles/&#34; &gt;Using different Github accounts with different private keys on Linux&lt;/a&gt;&lt;br&gt;
Just like mastering the .bashrc file can streamline your Linux experience, learning to juggle multiple GitHub accounts with ease could be the next step in optimizing your development workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Exploring how a JSON tool can creatively craft HTML might just be the unexpected twist you need to rethink the tools in your tech toolbox, much like recovering a deleted .bashrc file taught resilience and adaptability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-10-31-cult-of-not-done/&#34; &gt;The Cult of Not Done Manifesto&lt;/a&gt;&lt;br&gt;
Embrace the beauty of imperfection and continuous learning, just like when you’re tweaking your .bashrc file, with the “Cult of Not Done Manifesto” that celebrates the journey of endless improvement and the valuable lessons in every mistake.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>The Ultimate Interactive JQ Guide</title>
        <link>https://ishan.page/blog/2023-11-06-jq-by-example/</link>
        <pubDate>Mon, 06 Nov 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-11-06-jq-by-example/</guid>
        <description>&lt;img src="https://ishan.page/blog/2023-11-06-jq-by-example/numbers.jpg" alt="Featured image of post The Ultimate Interactive JQ Guide" /&gt;&lt;blockquote&gt;
&lt;p&gt;Cover Photo by &lt;a class=&#34;link&#34; href=&#34;https://www.pexels.com/photo/airport-bank-board-business-534216/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Pixabay&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;noscript&gt;
This article requires JavaScript. Sorry...
&lt;/noscript&gt;
&lt;p&gt;Has this ever happened to you?&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve just received a massive JSON file that looks like it was designed to confuse you. Or maybe you entered a command, and you got so much JSON that it looks incomprehensible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Level up your &lt;code&gt;jq&lt;/code&gt; skills with this accompanying &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io/data-science-project/beb98f1e-practice-the-basics-of-jq-using-pokemon-data?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;FREE practical project on DataWars&lt;/a&gt;&lt;/strong&gt; — enhance your skills through real-world challenges!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve partnered with &lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DataWars&lt;/a&gt; to include &lt;strong&gt;Hands On Practical Projects&lt;/strong&gt; that complement this &lt;code&gt;jq&lt;/code&gt; guide, designed to deepen your understanding and enhance your skills in a real-world setting.&lt;/p&gt;
&lt;p&gt;The first project, &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io/data-science-project/beb98f1e-practice-the-basics-of-jq-using-pokemon-data?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Pokemon Data Analysis&lt;/a&gt;&lt;/strong&gt; is available now.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io/data-science-project/beb98f1e-practice-the-basics-of-jq-using-pokemon-data?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Click Here to Start Practicing for FREE and LEVEL UP your jq skills&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The data you need is buried inside, and you&amp;rsquo;re dreading the hours it&amp;rsquo;ll take to extract and clean it up.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been there. I&amp;rsquo;ve &lt;code&gt;grep&lt;/code&gt;ped my way through JSON and written ad-hoc Python scripts to process it for me.&lt;/p&gt;
&lt;p&gt;But things don&amp;rsquo;t have to be like this.&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;jq&lt;/code&gt; is one of the best-kept secrets in the data processing world.&lt;/p&gt;
&lt;p&gt;Here are some scenarios where &lt;code&gt;jq&lt;/code&gt; could swoop in to save your day (and saves mine regularly):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Integrating with APIs in shell scripts often means handling JSON responses, requiring data extraction and manipulation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Data from different sources may need to be converted to or from JSON format for compatibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Managing software configuration files in JSON format can be a regular task.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extracting data from websites often results in dealing with JSON data that requires parsing and filtering.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Server logs and monitoring data often use JSON, necessitating parsing and analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Infra as Code tools like Ansible and Terraform use JSON-like configurations, requiring management. JSON is a subset of YAML, so every valid JSON file is also a valid YAML file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All examples are &lt;em&gt;✨fully interactive✨&lt;/em&gt;, so I encourage you to play around!&lt;br&gt;
In fact, I&amp;rsquo;ll be downright heartbroken if you don&amp;rsquo;t, because I put a lot of effort into it. You can edit both the input JSON data, and the jq program as well.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s dive in! We&amp;rsquo;ll start off easy, and get slowly deeper into the weeds.&lt;/p&gt;
&lt;h2 id=&#34;basic-operations&#34;&gt;Basic Operations&lt;/h2&gt;
&lt;h3 id=&#34;selecting-values&#34;&gt;Selecting values&lt;/h3&gt;
&lt;p&gt;Everything in &lt;code&gt;jq&lt;/code&gt; is a filter. The dot &lt;code&gt;.&lt;/code&gt; is used to select the current object or element, and we can put the property name after it to access a key from an object:&lt;/p&gt;
&lt;p&gt;&lt;jq-view name=&#34;example1&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}&#39; | \ 
jq &#39;.name&#39;
# Output: &#34;Alice&#34;
```
&lt;/noscript&gt;
&lt;h3 id=&#34;filtering-arrays&#34;&gt;Filtering Arrays&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;.[]&lt;/code&gt; notation is used to iterate over the elements of an array in a JSON document. It allows you to access each element of an array and perform operations on them.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;select()&lt;/code&gt; function is used to filter JSON data based on a specified condition or criteria. It is a powerful tool for extracting specific elements from a JSON document that meet certain conditions.&lt;/p&gt;
&lt;p&gt;Similiar to shell scripting, &lt;code&gt;jq&lt;/code&gt; works on a pipes-and-filters manner. We use the &lt;code&gt;|&lt;/code&gt; to send the data from one filter to the next.
&lt;jq-view name=&#34;example2&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}, {&#34;name&#34;: &#34;Bob&#34;, &#34;age&#34;: 25}]&#39; | \ 
jq &#39;.[] | select(.age &gt; 28)&#39;
# Output: {&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}
```
&lt;/noscript&gt;
&lt;h3 id=&#34;mapping-arrays&#34;&gt;Mapping Arrays&lt;/h3&gt;
&lt;p&gt;We can use the &lt;code&gt;map&lt;/code&gt; function to run any operation on every element of the array and return a new array containing the outputs of that operation:
&lt;jq-view name=&#34;example3&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[1, 2, 3, 4, 5]&#39; | jq &#39;map(. * 2)&#39;
# Output: [2,4,6,8,10]
```
&lt;/noscript&gt;
&lt;h3 id=&#34;combining-filters&#34;&gt;Combining Filters&lt;/h3&gt;
&lt;p&gt;The pipe operator &lt;code&gt;|&lt;/code&gt; can be used to chain as many filters or functions as we want:
&lt;jq-view name=&#34;example4&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}, {&#34;name&#34;: &#34;Bob&#34;, &#34;age&#34;: 25}]&#39; | jq &#39;.[] | select(.age &gt; 28) | .name&#39;
# Output: &#34;Alice&#34;
```
&lt;/noscript&gt;
&lt;h3 id=&#34;splitting-strings&#34;&gt;Splitting Strings&lt;/h3&gt;
&lt;p&gt;We can use the &lt;code&gt;split()&lt;/code&gt; function to a split a string on a particular separator character. &lt;br&gt;
Note also the usage of &lt;code&gt;.[0]&lt;/code&gt; to select the first index from the split array.&lt;/p&gt;
&lt;p&gt;&lt;jq-view name=&#34;example9&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;name&#34;: &#34;Alice Smith&#34;}&#39; | jq &#39;.name | split(&#34; &#34;) | .[0]&#39;
# Output: &#34;Alice&#34;
```
&lt;/noscript&gt;
&lt;h3 id=&#34;conditional-logic&#34;&gt;Conditional Logic&lt;/h3&gt;
&lt;p&gt;We can use &lt;code&gt;if&lt;/code&gt; to create expressions
&lt;jq-view name=&#34;example6&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}&#39; | jq &#39;if .age &gt; 18 then &#34;Adult&#34; else &#34;Child&#34; end&#39;
# Output: &#34;Adult&#34;
```
&lt;/noscript&gt;
&lt;h3 id=&#34;handling-null-values&#34;&gt;Handling Null Values&lt;/h3&gt;
&lt;p&gt;Null values can often mess up logic in our scripts, so we can filter them all out using &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;select&lt;/code&gt;
&lt;jq-view name=&#34;example17&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[1, null, 3, null, 5]&#39; | jq &#39;map(select(. != null))&#39;
# Output: [1,3,5]
```
&lt;/noscript&gt;
&lt;h3 id=&#34;formatting-output&#34;&gt;Formatting Output&lt;/h3&gt;
&lt;p&gt;Sometimes we don&amp;rsquo;t want JSON output. We want it in a particular string format.&lt;br&gt;
Note the use of the &lt;code&gt;-r&lt;/code&gt; flag, it makes the output raw. Without it, it would be displayed with quote marks around it.
&lt;jq-view name=&#34;example10&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}&#39; | jq -r &#39;&#34;Name: \(.name), Age: \(.age)&#34;&#39;
# Output: Name: Alice, Age: 30
```
&lt;/noscript&gt;
&lt;h3 id=&#34;multiple-outputs&#34;&gt;Multiple Outputs&lt;/h3&gt;
&lt;p&gt;Curly braces create a new object, which we can use for multiple outputs:
&lt;jq-view name=&#34;example5&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}&#39; | jq &#39;{name: .name, age: (.age + 5)}&#39;
# Output: {&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 35}
```
&lt;/noscript&gt;
&lt;h2 id=&#34;dealing-with-nested-items&#34;&gt;Dealing with Nested Items&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/russian_dolls.jpg&#34;
	width=&#34;800&#34;
	height=&#34;533&#34;
	srcset=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/russian_dolls_huda101acc57ff3d1327632db9c9883e36_28067_480x0_resize_q75_box.jpg 480w, https://ishan.page/blog/2023-11-06-jq-by-example/russian_dolls_huda101acc57ff3d1327632db9c9883e36_28067_1024x0_resize_q75_box.jpg 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;150&#34;
		data-flex-basis=&#34;360px&#34;
	
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.pexels.com/photo/two-yellow-and-red-ceramic-owl-figurines-4966180/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Photo by cottonbro studio&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;JSON is very commonly used to store nested objects, and we often need to traverse or manipulate such structures. &lt;code&gt;jq&lt;/code&gt; gives us all the tools we need to make it easy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Itching to practice what you&amp;rsquo;ve learned? Check out this &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io/data-science-project/beb98f1e-practice-the-basics-of-jq-using-pokemon-data?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;FREE practical project on DataWars&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve partnered with &lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DataWars&lt;/a&gt; to include &lt;strong&gt;Hands On Practical Projects&lt;/strong&gt; that complement this &lt;code&gt;jq&lt;/code&gt; guide, designed to deepen your understanding and enhance your skills in a real-world setting.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io/data-science-project/beb98f1e-practice-the-basics-of-jq-using-pokemon-data?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Click Here to Start Practicing for FREE right now&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;recursive-descent&#34;&gt;Recursive Descent&lt;/h3&gt;
&lt;p&gt;We can use &lt;code&gt;..&lt;/code&gt; to recursively descend through a tree of an object.&lt;/p&gt;
&lt;p&gt;&lt;jq-view name=&#34;example8&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;data&#34;: {&#34;value&#34;: 42, &#34;nested&#34;: {&#34;value&#34;: 24}}}&#39; | jq &#39;.. | .value?&#39;
# Output: null, 42, 24
```
&lt;/noscript&gt;
&lt;h3 id=&#34;filtering-nested-arrays&#34;&gt;Filtering Nested Arrays&lt;/h3&gt;
&lt;p&gt;&lt;jq-view name=&#34;example13&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;data&#34;: [{&#34;values&#34;: [1, 2, 3]}, {&#34;values&#34;: [4, 5, 6]}]}&#39; | jq &#39;.data[].values[] | select(. &gt; 3)&#39;
# Output: 4, 5, 6
```
&lt;/noscript&gt;
&lt;h3 id=&#34;flattening-nested-json-objects&#34;&gt;Flattening Nested JSON Objects&lt;/h3&gt;
&lt;p&gt;Often, we just want all the key-values, and flattening the object may be the most convenient way to go.&lt;/p&gt;
&lt;p&gt;This is an example where the operation we want to do is fairly straightforward, but the program looks way too scary.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to break it down:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It takes a JSON input and applies the paths function, which returns an array of all possible paths to the values in the JSON object. Each path is itself an array of keys or indices that can be used to access the value. For example, if the input is &lt;code&gt;{&amp;quot;a&amp;quot;: {&amp;quot;b&amp;quot;: 1, &amp;quot;c&amp;quot;: [2, 3]}}&lt;/code&gt;, then the paths function will return &lt;code&gt;[[], [&amp;quot;a&amp;quot;], [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;], [&amp;quot;a&amp;quot;, &amp;quot;c&amp;quot;], [&amp;quot;a&amp;quot;, &amp;quot;c&amp;quot;, 0], [&amp;quot;a&amp;quot;, &amp;quot;c&amp;quot;, 1]]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The query then assigns this array to a variable &lt;code&gt;$p&lt;/code&gt; using the &lt;code&gt;as&lt;/code&gt; keyword, which can be used to store intermediate results for later use.&lt;/li&gt;
&lt;li&gt;The query then applies the select function, which filters the array based on a condition. The condition is &lt;code&gt;getpath($p) | type != &amp;quot;object&amp;quot;&lt;/code&gt;, which means that only the paths that lead to values that are not objects are selected. The &lt;code&gt;getpath&lt;/code&gt; function takes a path and returns the value at that path in the JSON input. The &lt;code&gt;type&lt;/code&gt; function returns the type of the value, such as &lt;code&gt;“string”&lt;/code&gt;, &lt;code&gt;“number”&lt;/code&gt;, &lt;code&gt;“array”&lt;/code&gt;, or &lt;code&gt;“object”&lt;/code&gt;. For example, &lt;code&gt;getpath([&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;]) | type&lt;/code&gt; will return &lt;code&gt;“number”&lt;/code&gt; for the input &lt;code&gt;{&amp;quot;a&amp;quot;: {&amp;quot;b&amp;quot;: 1, &amp;quot;c&amp;quot;: [2, 3]}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The query then applies another pipe, which passes the filtered array to the next filter. The next filter is &lt;code&gt;($p | join(&amp;quot;.&amp;quot;)) + &amp;quot; = &amp;quot; + (getpath($p) | tostring)&lt;/code&gt;, which constructs a string for each path and its corresponding value. The &lt;code&gt;join&lt;/code&gt; function takes an array and concatenates its elements with a separator, in this case a dot. The &lt;code&gt;tostring&lt;/code&gt; function converts any value to a string representation. The &lt;code&gt;+&lt;/code&gt; operator concatenates strings. For example, &lt;code&gt;([&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;] | join(&amp;quot;.&amp;quot;)) + &amp;quot; = &amp;quot; + (getpath([&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;]) | tostring)&lt;/code&gt; will return &lt;code&gt;“a.b = 1”&lt;/code&gt; for the input &lt;code&gt;{&amp;quot;a&amp;quot;: {&amp;quot;b&amp;quot;: 1, &amp;quot;c&amp;quot;: [2, 3]}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The query then outputs the resulting strings, one per line, to the standard output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;jq-view name=&#34;example21&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;person&#34;: {&#34;name&#34;: {&#34;first&#34;: &#34;Alice&#34;, &#34;last&#34;: &#34;Smith&#34;}, &#34;age&#34;: 30}}&#39; | jq &#39;paths as $p | select(getpath($p) | type != &#34;object&#34;) | ($p | join(&#34;.&#34;)) + &#34; = &#34; + (getpath($p) | tostring)&#39;
# Output: &#34;person.name.first = Alice&#34;, &#34;person.name.last = Smith&#34;, &#34;person.age = 30&#34;
```
&lt;/noscript&gt;
&lt;h3 id=&#34;recursive-object-manipulation&#34;&gt;Recursive Object Manipulation&lt;/h3&gt;
&lt;p&gt;We can use the &lt;code&gt;recurse&lt;/code&gt; as well, to traverse a tree.
&lt;jq-view name=&#34;example18&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;data&#34;: {&#34;value&#34;: 42, &#34;nested&#34;: {&#34;value&#34;: 24}}}&#39; | jq &#39;recurse | .value? | select(. != null) | { value: (. * 5) } | add&#39;
# Output: 210, 120
```
&lt;/noscript&gt;
&lt;h3 id=&#34;complex-object-transformation&#34;&gt;Complex Object Transformation&lt;/h3&gt;
&lt;p&gt;&lt;jq-view name=&#34;example14&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;items&#34;: [{&#34;name&#34;: &#34;Apple&#34;, &#34;price&#34;: 1}, {&#34;name&#34;: &#34;Banana&#34;, &#34;price&#34;: 0.5}]}&#39; | jq &#39;.items | map({(.name): (.price * 2)}) | add&#39;
# Output: {&#34;Apple&#34;: 2, &#34;Banana&#34;: 1}
```
&lt;/noscript&gt;
&lt;h3 id=&#34;walk-through-object-and-apply-a-transformation-conditionally&#34;&gt;Walk through object and apply a transformation conditionally&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;walk()&lt;/code&gt; function provides a convenient way to traverse a nested object and apply some transformation to it.
&lt;jq-view name=&#34;example24&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;data&#34;: {&#34;values&#34;: [1, 2, 3], &#34;nested&#34;: {&#34;values&#34;: [4, 5, 6]}}}&#39; | jq &#39;walk(if type == &#34;number&#34; then . * 2 else . end)&#39;
# Output: {&#34;data&#34;:{&#34;values&#34;:[2,4,6],&#34;nested&#34;:{&#34;values&#34;:[8,10,12]}}}
```
&lt;/noscript&gt;
&lt;h2 id=&#34;statistical-operations&#34;&gt;Statistical Operations&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/stats.jpg&#34;
	width=&#34;800&#34;
	height=&#34;534&#34;
	srcset=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/stats_hue97aa36f055360b42fa6a58149f87076_53754_480x0_resize_q75_box.jpg 480w, https://ishan.page/blog/2023-11-06-jq-by-example/stats_hue97aa36f055360b42fa6a58149f87076_53754_1024x0_resize_q75_box.jpg 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;149&#34;
		data-flex-basis=&#34;359px&#34;
	
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a class=&#34;link&#34; href=&#34;https://www.pexels.com/photo/magnifying-glass-on-white-paper-with-statistical-data-5561913/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Leeloo Thefirst&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;jq&lt;/code&gt; is incredibly handy for doing quick and dirty statistical analysis in the field. Here&amp;rsquo;s most of the common operations related to that&lt;/p&gt;
&lt;h3 id=&#34;sorting-arrays&#34;&gt;Sorting Arrays&lt;/h3&gt;
&lt;p&gt;Sorting an array is a basic operation that is useful for many things in statistics.
&lt;jq-view name=&#34;example7&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[3, 1, 4, 2, 5]&#39; | jq &#39;sort&#39;
# Output: [1,2,3,4,5]
```
&lt;/noscript&gt;
&lt;h3 id=&#34;extracting-unique-values-from-an-array&#34;&gt;Extracting Unique Values from an Array&lt;/h3&gt;
&lt;p&gt;Extracting unique values from an array is another fairly basic operation that we need for many things.
&lt;jq-view name=&#34;example12&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[1, 2, 2, 3, 4, 4, 5]&#39; | jq &#39;unique&#39;
# Output: [1,2,3,4,5]
```
&lt;/noscript&gt;
&lt;h3 id=&#34;calculating-averages&#34;&gt;Calculating Averages&lt;/h3&gt;
&lt;p&gt;Calculating the mean or average of a dataset is a common statistical operation we may often need to do
&lt;jq-view name=&#34;example20&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;score&#34;: 90}, {&#34;score&#34;: 85}, {&#34;score&#34;: 95}]&#39; | jq &#39;map(.score) | add / length&#39;
# Output: 90
```
&lt;/noscript&gt;
&lt;h3 id=&#34;grouping-and-aggregating&#34;&gt;Grouping and Aggregating&lt;/h3&gt;
&lt;p&gt;We can group an array of objects by a particular key and get an aggregated value of the other keys fairly easily:
&lt;jq-view name=&#34;example11&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;category&#34;: &#34;A&#34;, &#34;value&#34;: 10}, {&#34;category&#34;: &#34;B&#34;, &#34;value&#34;: 20}, {&#34;category&#34;: &#34;A&#34;, &#34;value&#34;: 5}]&#39; | jq &#39;group_by(.category) | map({category: .[0].category, sum: map(.value) | add})&#39;
# Output: [{&#34;category&#34;: &#34;A&#34;, &#34;sum&#34;: 15}, {&#34;category&#34;: &#34;B&#34;, &#34;sum&#34;: 20}]
```
&lt;/noscript&gt;
&lt;h3 id=&#34;filtering-after-aggregation&#34;&gt;Filtering after Aggregation&lt;/h3&gt;
&lt;p&gt;&lt;jq-view name=&#34;example25&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;category&#34;: &#34;A&#34;, &#34;value&#34;: 10}, {&#34;category&#34;: &#34;B&#34;, &#34;value&#34;: 20}, {&#34;category&#34;: &#34;A&#34;, &#34;value&#34;: 5}]&#39; | jq &#39;group_by(.category) | map({category: .[0].category, sum: (map(.value) | add)}) | .[] | select(.sum &gt; 17)&#39;
# Output: {&#34;category&#34;:&#34;B&#34;,&#34;sum&#34;:20}
```
&lt;/noscript&gt;
&lt;h3 id=&#34;custom-aggregation-with-reduce&#34;&gt;Custom Aggregation with reduce&lt;/h3&gt;
&lt;p&gt;We can also use &lt;code&gt;reduce&lt;/code&gt; to perform a single-output aggregation from an array
&lt;jq-view name=&#34;example23&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;value&#34;: 10}, {&#34;value&#34;: 20}, {&#34;value&#34;: 30}]&#39; | jq &#39;reduce .[] as $item (0; . + $item.value)&#39;
# Output: 60
```
&lt;/noscript&gt;
&lt;h3 id=&#34;calculating-histogram-bins&#34;&gt;Calculating Histogram Bins&lt;/h3&gt;
&lt;p&gt;We may want to calculate a histogram from an array of data.
&lt;jq-view name=&#34;example22&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]&#39; | jq &#39;group_by(. / 5 | floor * 5) | map({ bin: .[0], count: length })&#39;
# Output: 
[
  {
    &#34;bin&#34;: 1,
    &#34;count&#34;: 4
  },
  {
    &#34;bin&#34;: 5,
    &#34;count&#34;: 5
  },
  {
    &#34;bin&#34;: 10,
    &#34;count&#34;: 5
  },
  {
    &#34;bin&#34;: 15,
    &#34;count&#34;: 1
  }
]
```
&lt;/noscript&gt;
&lt;h2 id=&#34;other-common-operations&#34;&gt;Other Common Operations&lt;/h2&gt;
&lt;p&gt;These are some other common operations I frequently find myself doing every day, but I couldn&amp;rsquo;t think of a better way to categorize them.&lt;/p&gt;
&lt;h3 id=&#34;extracting-values-based-on-multiple-conditions&#34;&gt;Extracting Values Based on Multiple Conditions&lt;/h3&gt;
&lt;p&gt;We can combine multiple conditions in a &lt;code&gt;select&lt;/code&gt; call. The &lt;code&gt;test()&lt;/code&gt; function is used to check if the passed string contains one of the substrings or not.
&lt;jq-view name=&#34;example15&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;[{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}, {&#34;name&#34;: &#34;Bob&#34;, &#34;age&#34;: 25}, {&#34;name&#34;: &#34;John&#34;, &#34;age&#34;: 35}]&#39; | jq &#39;map(select(.age &gt; 28 and (.name | test(&#34;a&#34;, &#34;i&#34;))))&#39;
# Output: [{&#34;name&#34;: &#34;Alice&#34;, &#34;age&#34;: 30}]
```
&lt;/noscript&gt;
&lt;h3 id=&#34;formatting-unix-timestamps&#34;&gt;Formatting Unix Timestamps&lt;/h3&gt;
&lt;p&gt;Various tools emit Unix Timestamps, and we can use the handy &lt;code&gt;strftime&lt;/code&gt; function to format it so it&amp;rsquo;s easier to understand at a glace.
&lt;jq-view name=&#34;example16&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;timestamp&#34;: 1630768200}&#39; | jq &#39;.timestamp | strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)&#39;
# Output: &#34;2021-09-04 15:10:00&#34;
```
&lt;/noscript&gt;
&lt;h3 id=&#34;enumerating-by-top-level-key-and-value&#34;&gt;Enumerating by Top Level Key and Value&lt;/h3&gt;
&lt;p&gt;&lt;jq-view name=&#34;example19&#34;&gt;&lt;/jq-view&gt;&lt;/p&gt;
&lt;noscript&gt;
```bash
echo &#39;{&#34;a&#34;: 1, &#34;b&#34;: 2, &#34;c&#34;: 3}&#39; | jq &#39;to_entries[] | &#34;\(.key) is \(.value)&#34;&#39;
# Output: &#34;a is 1&#34;, &#34;b is 2&#34;, &#34;c is 3&#34;
```
&lt;/noscript&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;Whew! That&amp;rsquo;s been a long article 😅 If you&amp;rsquo;re still here, then I appreciate you staying till the very end.&lt;/p&gt;
&lt;p&gt;I hope you&amp;rsquo;ve learned something new, and that you&amp;rsquo;ll be able to quickly identify use cases for &lt;code&gt;jq&lt;/code&gt; in your current workflow and apply your learnings there.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Enjoying this article so far? Check out this &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.datawars.io/data-science-project/beb98f1e-practice-the-basics-of-jq-using-pokemon-data?ref=ishan&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;FREE practical project on DataWars&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;how-does-this-article-work&#34;&gt;How Does This Article Work?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;I have used web components to create a custom component &lt;code&gt;&amp;lt;jq-view&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;There is some Javascript in this page which renders all the &lt;code&gt;&amp;lt;jq-view&amp;gt;&lt;/code&gt;s when the page is loaded.&lt;/li&gt;
&lt;li&gt;The WebAssembly build of &lt;code&gt;jq&lt;/code&gt;, as well as all the code for calling out to it is provided by BioWasm.&lt;/li&gt;
&lt;li&gt;I have used AlpineJs to make the examples interactive. When the button is clicked, it sends an event to a listener, which makes it run &lt;code&gt;jq&lt;/code&gt; and then update the output.&lt;/li&gt;
&lt;li&gt;Since I am not good at front-end, this was a substantial learning experience for me.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;get-in-touch&#34;&gt;Get In Touch&lt;/h3&gt;
&lt;p&gt;If you have any suggestions on how this may be improved, errors that I might have made, or you just want to discuss any other topic, please feel free to &lt;a class=&#34;link&#34; href=&#34;mailto:hello@ishan.page&#34; &gt;email me&lt;/a&gt;. I always love to hear from you.&lt;/p&gt;
&lt;h3 id=&#34;extra-resources&#34;&gt;Extra Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://jqlang.github.io/jq/manual/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;JQ Manual&lt;/a&gt;: The official JQ manual. Covers everything, but a bit difficult to digest.&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://zwischenzugs.com/2023/06/27/learn-jq-the-hard-way-part-i-json/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Learn JQ the Hard Way&lt;/a&gt;: A good series of blog posts covering introductory theoretical aspects of jq.&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://sandbox.bio/tutorials?id=jq-intro&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;JSON Wrangling with jq&lt;/a&gt;: Another interactive series on jq that dives into more detail on the theoretical aspects.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;changelog&#34;&gt;Changelog&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2023-11-29
&lt;ul&gt;
&lt;li&gt;Add a &amp;ldquo;Reset&amp;rdquo; button&lt;/li&gt;
&lt;li&gt;Fixed some examples that were incorrect in the non javascript version of this page&lt;/li&gt;
&lt;li&gt;Added some more resources&lt;/li&gt;
&lt;li&gt;Added explanation for &lt;a class=&#34;link&#34; href=&#34;#flattening-nested-json-objects&#34; &gt;Flattening Nested JSON Objects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
After mastering jq through interactive examples, you’ll be intrigued by how I creatively used it to generate HTML, pushing the boundaries of conventional tool use and highlighting the value of adaptability in tech.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-09-18-pem-linux/&#34; &gt;Generate PEM file for any Linux user&lt;/a&gt;&lt;br&gt;
After mastering jq for JSON manipulation, learning to create a secure 4096-bit RSA key pair could be your next step in enhancing your data handling and security skills.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-04-addendum-webfinger/&#34; &gt;Addendum: What&#39;s a Webfinger?&lt;/a&gt;&lt;br&gt;
Unlock the secrets of JSON and the fediverse by exploring how Webfinger’s API can streamline your data discovery and user profile management, complementing your newfound jq skills.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>The Cult of Not Done Manifesto</title>
        <link>https://ishan.page/blog/2023-10-31-cult-of-not-done/</link>
        <pubDate>Tue, 31 Oct 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-10-31-cult-of-not-done/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;To all those who ask why I haven&amp;rsquo;t been putting more posts out, this is for you&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dear Members of the Cult of Not Done,&lt;/p&gt;
&lt;p&gt;I present to you a manifesto of not done. This was inspired by &lt;a class=&#34;link&#34; href=&#34;https://medium.com/@bre/the-cult-of-done-manifesto-724ca1c2ff13&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Kio Stark and Bre Pettis&lt;/a&gt;, and written over five days because it was, obviously, not done.&lt;/p&gt;
&lt;h1 id=&#34;the-cult-of-not-done-manifesto&#34;&gt;The Cult of Not Done Manifesto&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;There are four states of being. Not knowing, action, refinement, and completion.&lt;/li&gt;
&lt;li&gt;Accept that everything is a draft. We have to make it better before we can be done.&lt;/li&gt;
&lt;li&gt;We live in the editing stage. Nothing is ever done because it&amp;rsquo;s always being improved.&lt;/li&gt;
&lt;li&gt;Pretending you know what you’re doing is almost the same as knowing what you are doing, but not good enough. So spend all your time making things perfect.&lt;/li&gt;
&lt;li&gt;Embrace procrastination. If you wait more than a week to get an idea done, give it more time. Your subconscious needs to think more, and it will give you the answer soon.&lt;/li&gt;
&lt;li&gt;The point of being done is to finish, and until we don&amp;rsquo;t, we can&amp;rsquo;t get other things done.&lt;/li&gt;
&lt;li&gt;If you&amp;rsquo;re never done, you can throw it away.&lt;/li&gt;
&lt;li&gt;Laugh at those who settle. It’s boring and keeps you from being perfection.&lt;/li&gt;
&lt;li&gt;People without dirty hands are wrong. Doing something makes you right. The more time you spend trying different things and not being done, the more authority you have on it.&lt;/li&gt;
&lt;li&gt;Failure and mistakes are natural and to be expected since you&amp;rsquo;re not done yet.&lt;/li&gt;
&lt;li&gt;Destruction is a force of progress. Start over often with increased scope to make your creation perfect.&lt;/li&gt;
&lt;li&gt;If you have an idea, never publish it on the internet, then it will be stolen from you.&lt;/li&gt;
&lt;li&gt;In Progress is the engine of more.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-hello-world/&#34; &gt;Hello World&lt;/a&gt;&lt;br&gt;
Embrace the journey of perpetual improvement and see how one author’s quest to revamp their digital space mirrors the “Cult of Not Done Manifesto’s” ethos, making it a perfect next read for you.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-10-15-systemd-discord-notify/&#34; &gt;Discord Notifications from Systemd&lt;/a&gt;&lt;br&gt;
Embrace the spirit of never-ending improvement by learning how to keep your Discord community in the loop with real-time service updates, a perfect blend of progress and communication.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-05-natural-selection-misconceptions/&#34; &gt;On &amp;quot;Natural Selection&amp;quot; and &amp;quot;Survival of the fittest&amp;quot;&lt;/a&gt;&lt;br&gt;
Exploring how the “Cult of Not Done Manifesto” champions the beauty of perpetual progress, you might find it fascinating to see how misconceptions around “natural selection” reveal the dangers of misinterpreting continuous improvement in the context of evolution and society.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Dear past me, use the flags</title>
        <link>https://ishan.page/blog/2023-07-26-use-the-flags-luke/</link>
        <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-26-use-the-flags-luke/</guid>
        <description>&lt;p&gt;Dear past me,&lt;/p&gt;
&lt;p&gt;I know you&amp;rsquo;ve just launched your first desktop application. It&amp;rsquo;s a nightmare isn&amp;rsquo;t it? Well you&amp;rsquo;re in for a bigger one.&lt;/p&gt;
&lt;p&gt;Your boss calls you, and they need a new feature immediately. You bang it out and send out the update.&lt;/p&gt;
&lt;p&gt;Oh yeah, that&amp;rsquo;s right. You didn&amp;rsquo;t include an update mechanism. Please use one, you&amp;rsquo;ll save yourself a lot of pain.&lt;/p&gt;
&lt;p&gt;You send out the update to users, but soon you find out everyone hasn&amp;rsquo;t updated yet. The boss &lt;strong&gt;insists&lt;/strong&gt; that people on an older app version shouldn&amp;rsquo;t be able to use it.&lt;/p&gt;
&lt;p&gt;But you didn&amp;rsquo;t include a forced version based lockout mechanism either. Well, you&amp;rsquo;ll remember that for next time!&lt;/p&gt;
&lt;p&gt;Desperate times call for desperate measures, and you decide to break the server so it returns bad data to old app versions. Never mind that this permanently corrupts the local database and will require future tech support to help them clear their cache. But that&amp;rsquo;s future you&amp;rsquo;s problem.&lt;/p&gt;
&lt;p&gt;The boss is happy, the app is chugging along. This cycle repeats a couple more times in various ways.&lt;/p&gt;
&lt;p&gt;Save yourself the pain next time. Implement a feature flag / version system. Later, it&amp;rsquo;ll even help you roll out features to users incrementally.&lt;/p&gt;
&lt;p&gt;Use the flags, Luke.&lt;/p&gt;
&lt;p&gt;Sincerely,
Present me&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2014-09-07-gamedev-ideas/&#34; &gt;Gamedev Ideas&lt;/a&gt;&lt;br&gt;
Explore how a programmer’s journey evolves from tackling technical challenges to creating unique game concepts that reflect on the quirks of development work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-03-08-wsl-time-drift/&#34; &gt;Fix WSL time drift&lt;/a&gt;&lt;br&gt;
After tackling the challenges of version control in your first project, discovering how to fix a sneaky bug in WSL2 that messes with time-sensitive operations could be your next tech lifesaver!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-05-08-windows-xampp-postgres/&#34; &gt;Install Postgres into XAMPP on Windows&lt;/a&gt;&lt;br&gt;
After tackling the challenges of your first desktop application, learning how to seamlessly integrate Postgres with XAMPP could be your next step towards mastering local development environments and avoiding past pitfalls.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Analgesia, Pain, and the Shape of The Brain</title>
        <link>https://ishan.page/blog/2023-07-15-analgesia-pain-brain/</link>
        <pubDate>Sat, 15 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-15-analgesia-pain-brain/</guid>
        <description>&lt;p&gt;I was returning from Saturday brunch with my friend a month or so ago. We took the metro back from the restaurant, and it was quite crowded. While disembarking from the metro, my leg slipped (or maybe I was pushed, I don&amp;rsquo;t know), and got lodged in the gap between the train and the platform. In my vigorous attempts to free myself, I twisted one knee and scraped the other.&lt;/p&gt;
&lt;p&gt;Thankfully, I reached home safely, but as I lay in bed that night, writhing in pain, I found my mind wandering back to 2020. The summer of the lockdown, I had found myself quite enamoured with a certain book, &lt;em&gt;PiHKAL: A Chemical Love Story&lt;/em&gt;. The main title, &lt;em&gt;PiHKAL&lt;/em&gt;, is an acronym that stands for &amp;ldquo;Phenethylamines I Have Known and Loved.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PiHKAL&lt;/em&gt;, and its sequel, &lt;em&gt;TiHKAL&lt;/em&gt; are strange, yet fascinating books. Each is divided into two parts: &amp;ldquo;The Love Story&amp;rdquo;, and &amp;ldquo;The Chemistry&amp;rdquo;. Most books about science and scientists often focus either on the science itself, or on the scientist and their thoughts or moral flaws of character. But &lt;em&gt;PiHKAL&lt;/em&gt; is different. It tells the story of not only the science, but also that of the scientist, and how his research shapes his personality, his personal life, and how they shape the research back. It&amp;rsquo;s a long (2500+ pages with the sequel) read, but it is &lt;strong&gt;worth it&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-thumb-and-the-knee&#34;&gt;The Thumb and the Knee&lt;/h2&gt;
&lt;p&gt;In the first chapter of the book, the narrator recounts his experience as a Navy man during the Second World War. On a destroyer in the middle of the Atlantic in the winter, he contracts an infection on his thumb that causes him immense pain. He required surgery, which wasn&amp;rsquo;t possible at sea, so all that could be done by the Navy medics was to manage his pain:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The man with the needle would interrupt a good rolling poker game to ask me how I was feeling. I would look at my thumb and say, &amp;ldquo;It&amp;rsquo;s a little worse,&amp;rdquo; or &amp;ldquo;It&amp;rsquo;s a little better,&amp;rdquo; and put my arm out for another morphine shot, then immerse myself again in the poker game. I knew the pain was there, and I could report on the intensity of it with accuracy, but it didn&amp;rsquo;t bother me. I could play poker, I could deal, I could judge the opposition, and I could bet shrewdly, and I came out ahead more than behind. My left thumb was viciously painful, but the pain just didn&amp;rsquo;t get in my way. It was fascinating to me that one could be hurting, in agony, and that the administering of a little bit of a chemical that came from some poppy flowers somewhere, could make it all quite unimportant.&lt;br&gt;
&lt;br/&gt;
This is what is meant by central analgesia. The pain is not deadened; it is still there. The site of action is not the thumb but, rather, the brain. The problem is simply no longer of concern.   &lt;br&gt;
&lt;br/&gt;
Morphine is a pretty remarkable drug.&lt;br&gt;
&lt;br/&gt;
-&lt;em&gt;PiHKAL&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I got to thinking about how I had chosen to manage my own pain:&lt;/p&gt;
&lt;p&gt;I put Moov (Diclofenac spray) on the knee which had been twisted.&lt;/p&gt;
&lt;p&gt;When diclofenac spray is applied to the skin, it is absorbed through the skin and penetrates into the underlying tissues. Once absorbed, diclofenac works by preventing the body from making chemicals called prostaglandins. Prostaglandins are produced at the place of injury, and are responsible for causing pain, swelling, and inflammation. By not letting the body make prostaglandins, diclofenac helps to reduce these symptoms in the affected area.&lt;/p&gt;
&lt;p&gt;In other words, the spray stopped my knee from telling my brain it was &amp;ldquo;hurt&amp;rdquo;. It also had a host of &amp;ldquo;counter-irritants&amp;rdquo; which overloaded the pain receptors with other sensations (a notable burning one) which simply didn&amp;rsquo;t let the brain feel the full magnitude of the pain. Scientists call this &amp;ldquo;working on the periphery.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Clever&amp;rdquo;, I thought to myself.&lt;/p&gt;
&lt;p&gt;The spray wasn&amp;rsquo;t magical by any means, but it did provide enough relief for me to be able to fall asleep.&lt;/p&gt;
&lt;h2 id=&#34;on-pain&#34;&gt;On Pain&lt;/h2&gt;
&lt;p&gt;Pain is essentially a way for our body to communicate with us, alerting us that something isn&amp;rsquo;t quite right. Think of it as a warning system, like a fire alarm. When we experience pain, it&amp;rsquo;s our body&amp;rsquo;s way of saying, &amp;ldquo;Hey, pay attention! Something needs your immediate attention here.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So, how does pain work? Well, it all starts with specialized nerve endings. These are found throughout our body, including our skin, muscles, organs, and even bones. When we touch a hot stove or getting a paper cut, these spring into action. It sends an electrical signal to the brain.&lt;/p&gt;
&lt;p&gt;Now, the brain plays a crucial role in processing and interpreting this signal. It evaluates the intensity, location, and quality of the pain. It also takes into account your previous experiences, emotions, and context to give the pain a &lt;strong&gt;subjective meaning&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You see, pain is not just a physical sensation. It&amp;rsquo;s influenced by various factors, including our emotions, thoughts, and memories. That&amp;rsquo;s why the same injury can be perceived differently by different people. For example, a minor bruise might be extremely painful to one person but relatively tolerable to another.&lt;/p&gt;
&lt;p&gt;Interestingly, pain can also serve as a protective mechanism. Keeping with the stove analogy, the pain you feel immediately forces your hand to avoid further hurt.&lt;/p&gt;
&lt;h2 id=&#34;growth-and-the-nature-of-suffering&#34;&gt;Growth and the nature of suffering&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“Pain is inevitable, but suffering is optional,” is a Buddhist saying that points to a fundamental truth of existence, which is that pain and affliction are an inherent part of life: we contract illnesses, get wounded, lose our loved ones, our possessions, our social status. But despite the hardships we encounter, the degree of suffering we generate still varies per person. The greatest misfortune hardly affects some people, while the slightest inconvenience leads other people into states of deep agony. Thus, could it be that suffering is something we can manage and doesn’t always have to result from pain?&lt;br&gt;
&lt;br&gt;
- &lt;a class=&#34;link&#34; href=&#34;https://einzelganger.co/why-pain-is-inevitable-but-suffering-is-optional/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Why Pain is Inevitable, but Suffering is Optional&lt;/a&gt;, Einzelganger&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All growth brings with it naturally, some degree of pain. This is because growth requires us to get out of our comfort zone, which causes us psychological pain. But that pain is justifiable, as long as it helps us to achieve the growth that we are aiming for. This pain should not be confused with suffering.&lt;/p&gt;
&lt;p&gt;Suffering is pain that exists without purpose. It has no higher goals.&lt;/p&gt;
&lt;h2 id=&#34;the-doctor-will-see-you-now&#34;&gt;The Doctor will see you now&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Go to the doctor&amp;rdquo;, my mother said after observing me hobbling around with my bandaged leg, &amp;ldquo;He will make it better&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The doctor was sympathetic, emphasizing how lucky I had been to avoid further harm. He then prescribed an X-Ray, and paracetamol.&lt;/p&gt;
&lt;p&gt;Paracetamol, also known as acetaminophen, is a commonly used medication to relieve pain and reduce fever. Its exact mechanism of action is not fully understood, but it is believed to work through multiple mechanisms, but primarily in the central nervous system (CNS). It is believed to inhibit the synthesis of prostaglandins in the brain, which can help reduce the perception of pain and lower fever.&lt;/p&gt;
&lt;p&gt;Additionally, paracetamol may act on other neurotransmitter systems in the brain, such as the endocannabinoid system, which could contribute to its pain relieving and fever relieving effects too.&lt;/p&gt;
&lt;p&gt;It might be useful to take a moment to note the purpose of a fever: The body raises the temperature to make it hard for the infector to survive.&lt;/p&gt;
&lt;p&gt;So the doctor isn&amp;rsquo;t actually making anything better in this case. When we take paracetamol for a fever, or to relieve pain, it doesn&amp;rsquo;t actually deal with the root cause. It only addresses the symptoms, and fakes our brain into believing that all is okay while the body takes its own sweet time to heal itself.&lt;/p&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;What prompted me to write this was the analogous behaviour to the doctors that I have observed in different software teams that I have worked with. Often, when we are presented with a problem: a bug that is being faced, or some latent issue found in the system, we attempt to treat the symptom, rather than find the root cause:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Too many errors? Just silence it. PHP even comes with a handy &lt;code&gt;@&lt;/code&gt; operator&lt;/li&gt;
&lt;li&gt;Program keeps crashing? Just make systemd restart it.&lt;/li&gt;
&lt;li&gt;Program OOM&amp;rsquo;s? Just run it on a bigger machine&lt;/li&gt;
&lt;li&gt;Database query takes time? Just cache it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, this is bad practice, but bad practice can&amp;rsquo;t always be avoided due to organizational issues. Yes, doctors have their perfectly valid reasons for treating the symptoms (because the human body is difficult and it takes a lot of time to fully understand root causes)&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/&#34; &gt;Programming &amp;quot;with the grain&amp;quot;&lt;/a&gt;&lt;br&gt;
Exploring the depths of how we perceive and manage pain, you might find the next article intriguing as it shifts the focus from the human mind to the digital realm, revealing how understanding and aligning with the inherent structures of programming can lead to more efficient and effective solutions, much like the philosophical approach to pain management.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recommended reading not found for slug or filename: &#39;post/power-digits-log-formula-trick&#39;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-05-natural-selection-misconceptions/&#34; &gt;On &amp;quot;Natural Selection&amp;quot; and &amp;quot;Survival of the fittest&amp;quot;&lt;/a&gt;&lt;br&gt;
Exploring how misconceptions shape our world, this next article uncovers the truth behind “natural selection” and “survival of the fittest,” much like the first article dissected our understanding of pain and its management.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Programming &#34;with the grain&#34;</title>
        <link>https://ishan.page/blog/2023-07-09-programming-with-the-grain/</link>
        <pubDate>Sun, 09 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-09-programming-with-the-grain/</guid>
        <description>&lt;p&gt;When I was a kid, I observed that most sheets of paper have a sort of &amp;ldquo;direction&amp;rdquo; inside them. It&amp;rsquo;s not possible to tell by looking, but there&amp;rsquo;s a simple experiment to show:&lt;/p&gt;
&lt;p&gt;Rip the same sheet of paper left and right, then up and down. One of the two will have a smooth, straight, nice-looking rip, while the other will have a rough, uneven edge.&lt;/p&gt;
&lt;p&gt;Later, as a teenager, I learned that this is called the &amp;ldquo;grain&amp;rdquo; of the paper, and that this also applies to &lt;a class=&#34;link&#34; href=&#34;https://gillette.com/en-us/shaving-tips/how-to-shave/against-the-grain&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;shaving&lt;/a&gt; and &lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Wood_grain&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;woodworking&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have observed that computers and programs exhibit similiar characteristics which aren&amp;rsquo;t obvious at first. Any given computer, platform, problem and program has a &amp;ldquo;grain&amp;rdquo; too. A hidden, but present underlying &amp;ldquo;optimal&amp;rdquo; (may I even call it &amp;ldquo;natural&amp;rdquo;) structure of how data flows and the factorization of the various components that would constitute it. &lt;a class=&#34;link&#34; href=&#34;https://wiki.c2.com/?WithTheGrain&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Others&lt;/a&gt; seem to have observed it too.&lt;/p&gt;
&lt;h2 id=&#34;a-tryst-with-locality&#34;&gt;A tryst with locality&lt;/h2&gt;
&lt;p&gt;Memory can be a funny thing, both when it comes to the self, and to computers. Take the following two pieces of C++ code for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// First Example
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;element&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// Do something with the thing item
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Second Example
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;element&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// Do something with the thing item
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Running 100 iterations on a 10x10 array filled with 0s, the first example takes 221ns and the second takes 223ns. That&amp;rsquo;s not even 1%, and maybe it can be chalked up to statistial error. But what happens when we go bigger?&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Array Size&lt;/th&gt;
&lt;th&gt;Average 1&lt;/th&gt;
&lt;th&gt;Average 2&lt;/th&gt;
&lt;th&gt;Best 1&lt;/th&gt;
&lt;th&gt;Best 2&lt;/th&gt;
&lt;th&gt;Worst 1&lt;/th&gt;
&lt;th&gt;Worst 2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10x10&lt;/td&gt;
&lt;td&gt;221.52ns&lt;/td&gt;
&lt;td&gt;223.42ns&lt;/td&gt;
&lt;td&gt;205ns&lt;/td&gt;
&lt;td&gt;211ns&lt;/td&gt;
&lt;td&gt;480ns&lt;/td&gt;
&lt;td&gt;402ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100x100&lt;/td&gt;
&lt;td&gt;24646ns&lt;/td&gt;
&lt;td&gt;13296ns&lt;/td&gt;
&lt;td&gt;8163ns&lt;/td&gt;
&lt;td&gt;8266ns&lt;/td&gt;
&lt;td&gt;143007ns&lt;/td&gt;
&lt;td&gt;32424ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1000x1000&lt;/td&gt;
&lt;td&gt;806953ns&lt;/td&gt;
&lt;td&gt;1.33ms&lt;/td&gt;
&lt;td&gt;645242ns&lt;/td&gt;
&lt;td&gt;951179ns&lt;/td&gt;
&lt;td&gt;1.5ms&lt;/td&gt;
&lt;td&gt;3.44ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10000x10000&lt;/td&gt;
&lt;td&gt;81.3ms&lt;/td&gt;
&lt;td&gt;675.34ms&lt;/td&gt;
&lt;td&gt;70.85ms&lt;/td&gt;
&lt;td&gt;632.21ms&lt;/td&gt;
&lt;td&gt;101.65ms&lt;/td&gt;
&lt;td&gt;776.79ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/locality-graph.png&#34;
	width=&#34;848&#34;
	height=&#34;631&#34;
	srcset=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/locality-graph_hu7cdb646437aff528298bf51dbec56079_40879_480x0_resize_box_3.png 480w, https://ishan.page/blog/2023-07-09-programming-with-the-grain/locality-graph_hu7cdb646437aff528298bf51dbec56079_40879_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Graph&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;134&#34;
		data-flex-basis=&#34;322px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;The first example performs dramatically better! But why? What is it doing different? Let&amp;rsquo;s take a closer look:&lt;/p&gt;
&lt;p&gt;Imagine a 3 x 3 array. It might look 2D to us:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1,2,3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4,5,6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;7,8,9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;But, 2D arrays are an abstraction. Memory in computers is single dimensional, so the computer stores this as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1,2,3,4,5,6,7,8,9
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This drastic performance difference is because of the concept of &lt;a class=&#34;link&#34; href=&#34;https://eng.libretexts.org/Courses/Delta_College/Operating_System%3A_The_Basics/01%3A_The_Basics_-_An_Overview/1.7_Cache_Memory/1.7.2_Cache_Memory_-_Locality_of_reference&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Locality of Reference&lt;/a&gt; and how C++ stores your data in memory. Since C++ uses &lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Row-_and_column-major_order&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;row-major&lt;/a&gt; ordering, accessing elements in order of rows (as in the first example) goes &lt;em&gt;with the grain&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Since the elements are stored are more likely to be located nearby in memory, the processor can also &amp;ldquo;cheat&amp;rdquo; and load a contiguous chunk of memory into the cache, which allows for much faster access. However, when iterating by column (or &lt;em&gt;against the grain&lt;/em&gt;), the processor can&amp;rsquo;t cache the columns from memory, because &lt;em&gt;the columns don&amp;rsquo;t exist next to each other&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s more to the story than performance though.&lt;/p&gt;
&lt;h2 id=&#34;the-terrible-tale-of-pthreads&#34;&gt;The terrible tale of pthreads&lt;/h2&gt;
&lt;p&gt;When someone says &amp;ldquo;multithreading&amp;rdquo;, they almost always mean threading with reference to the POSIX threads model. People &lt;a class=&#34;link&#34; href=&#34;https://softwareengineering.stackexchange.com/questions/81003/how-to-explain-why-multi-threading-is-difficult&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;often complain&lt;/a&gt; about how difficult and error prone the usage of threads are.&lt;/p&gt;
&lt;p&gt;However, what most people won&amp;rsquo;t tell you, is that &lt;strong&gt;POSIX threads are against the grain of computers&lt;/strong&gt;. While threads can run concurrently, the underlying architecture does not directly resemble the interrupt-driven behavior of CPUs. Thread scheduling and synchronization are typically handled by the operating system, abstracting away the low-level hardware details.&lt;/p&gt;
&lt;p&gt;The &lt;a class=&#34;link&#34; href=&#34;https://swtch.com/~rsc/thread/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Communicating Sequential Processes&lt;/a&gt; (CSP) concurrency model, pioneered by Tony Hoare, focuses on communication and synchronization between concurrent processes rather than explicit thread management. In CSP, processes communicate by sending and receiving messages through channels, and synchronization is achieved through the coordination of message passing. This model aligns more closely with the interrupt-based architecture of CPUs. Go is based on this model.&lt;/p&gt;
&lt;h2 id=&#34;when-in-rome&#34;&gt;When in Rome&lt;/h2&gt;
&lt;p&gt;When in Rome, one should always do as Romans do. When programming, this often extends to following the idioms of the platform and language you are working on, as well as the culture and coding guidelines of the team. That&amp;rsquo;s why, when in Python land, you follow the Zen of Python, and in Go land, you don&amp;rsquo;t use a full stack framework. This is because going against the grain of the platform makes it more difficult, and you&amp;rsquo;ll definitely know when you&amp;rsquo;re doing it.&lt;/p&gt;
&lt;p&gt;As &lt;a class=&#34;link&#34; href=&#34;http://web.archive.org/web/20201025220805/https://sites.google.com/site/yacoset/Home/signs-that-you-re-a-good-programmer&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;yacoset&lt;/a&gt; puts it so elegantly,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You cannot think &amp;ldquo;Fire rearward missile&amp;rdquo; and then translate it to Russian, you &lt;strong&gt;must think in Russian&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Consider the following program in Python that someone from a C background might write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Sum: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This goes against the grain, and is non idiomatic Python.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Sum: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The idiomatic Python version utilizes the built-in sum() function with a range to directly calculate the sum of numbers from 1 to 10. It then uses an f-string to format the output and achieves the same functionality in a more concise and Pythonic way.&lt;/p&gt;
&lt;p&gt;How about this code in Go?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nx&#34;&gt;urls&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://example.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;https://google.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;https://github.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;wg&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;sync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;WaitGroup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;sync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Mutex&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;range&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;urls&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nx&#34;&gt;wg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;go&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;defer&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;wg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Done&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Error fetching %s: %s\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Unlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;defer&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ReadAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Error reading response body from %s: %s\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Unlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;URL: %s, Length: %d\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nx&#34;&gt;mu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Unlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;p&#34;&gt;}(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nx&#34;&gt;wg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In this example, we manually manage the &amp;ldquo;threads&amp;rdquo; using the &lt;code&gt;sync.WaitGroup&lt;/code&gt;. Each URL is processed by a separate thread, and synchronization is achieved using the &lt;code&gt;sync.Mutex&lt;/code&gt; to protect shared access to the console output.&lt;/p&gt;
&lt;p&gt;While this approach still accomplishes concurrent processing, it deviates from the idiomatic use of goroutines and channels in Go and involves lower-level thread management.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;s&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nx&#34;&gt;urls&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://example.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;https://google.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;https://github.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;c1&#34;&gt;// Create a channel to receive the results
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;	&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;chan&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;c1&#34;&gt;// Launch a goroutine for each URL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;	&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;range&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;urls&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;go&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fetchURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;c1&#34;&gt;// Collect the results
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;	&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;urls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nx&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Fetched:&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fetchURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;chan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Error fetching %s: %s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;defer&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ReadAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Error reading response body from %s: %s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nx&#34;&gt;results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;URL: %s, Length: %d&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now, we launch a goroutine for each URL, and each goroutine fetches the content of the URL. The results are then sent back through the results channel. Finally, we collect the results and print them.&lt;/p&gt;
&lt;p&gt;This approach, (while still not optimal) aligns with the idiomatic way of utilizing goroutines and channels for concurrent tasks in Go and is much more readable and thus maintainable in the future.&lt;/p&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;Further quoting yacoset,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s a thousand computer languages because there&amp;rsquo;s a thousand classes of problems we can solve with software. In the 1980s, after the Macintosh debut, a hundred DOS products were ported to the new mouse-driven platform by clubbing the Alto-inspired UI over the head and brute-forcing the keyboard-driven paradigms of PCs into the Mac&amp;rsquo;s visual atmosphere. Most of these were rejected by Apple or the market, and if they came back for a second try they came back because somebody flipped open the spiral-bound HIG and read it sincerely.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As programmers, I think we should take pride in our craft, and always try to program with the grain of the platform we are on. Many benefits await!&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Explore how bending the rules with a tool like jq for HTML generation can spark creativity in your coding, much like programming “with the grain” harnesses the natural power of languages for better results.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-15-analgesia-pain-brain/&#34; &gt;Analgesia, Pain, and the Shape of The Brain&lt;/a&gt;&lt;br&gt;
Exploring the depths of efficiency and problem-solving, you’ll find intriguing parallels between optimizing code in programming and navigating the complexities of pain management in life.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-05-natural-selection-misconceptions/&#34; &gt;On &amp;quot;Natural Selection&amp;quot; and &amp;quot;Survival of the fittest&amp;quot;&lt;/a&gt;&lt;br&gt;
Just like understanding the “grain” of programming can optimize your code, unraveling the true meaning of “natural selection” might reshape your view on how we apply Darwin’s theories in society today.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>On &#34;Natural Selection&#34; and &#34;Survival of the fittest&#34;</title>
        <link>https://ishan.page/blog/2023-07-05-natural-selection-misconceptions/</link>
        <pubDate>Wed, 05 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-05-natural-selection-misconceptions/</guid>
        <description>&lt;p&gt;The term Natural Selection is often misused, with people saying things like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;natural selection at its finest&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;he&amp;rsquo;s about to win a Darwin Award&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;when they see people doing things that are questionable.&lt;/p&gt;
&lt;p&gt;Not only is this a huge festering pool of negativity, but it actually totally misses the point of natural selection.&lt;/p&gt;
&lt;p&gt;Natural selection is the process by which those animals and plants which are &lt;strong&gt;best suited to the conditions in which they live&lt;/strong&gt; have more young and live longer.&lt;/p&gt;
&lt;p&gt;It is not a matter of only the best individuals of a species surviving, but those that are best adapted to their environment.&lt;/p&gt;
&lt;h2 id=&#34;on-survival-of-the-fittest&#34;&gt;On &amp;ldquo;Survival of the Fittest&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Darwin didn&amp;rsquo;t say &amp;ldquo;survival of the fittest&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Evolutionary biologists certainly aren&amp;rsquo;t happy with the way it is used by most people, and negative connotations it has in popular culture. It also hides and smoothes over the highly complex nature of natural selection, so modern biologists prefer and almost exclusively use the term natural selection instead.&lt;/p&gt;
&lt;p&gt;So where does it come from? Why do we use it the way we do?&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Herbert_Spencer&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Herbert Spencer&lt;/a&gt; gave us the phrase in his 1864 book, &lt;em&gt;Principles of Biology&lt;/em&gt;, published 5 years after Darwin&amp;rsquo;s &lt;em&gt;On the Origin of Species&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;He correlated his conservative ideas about economics and what Darwin had written about evolution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This survival of the fittest, which I have here sought to express in mechanical terms, is that which Mr. Darwin has called ‘natural selection’, or the preservation of favored races in the struggle for life.&lt;br&gt;
- &lt;em&gt;Principles of Biology&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Spencer later uses it to argue for things like &amp;ldquo;might is right&amp;rdquo; in his 1884 work &lt;em&gt;The Man Versus the State&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thus by survival of the fittest, the militant type of society becomes characterized by profound confidence in the governing power, joined with a loyalty causing submission to it in all matters whatever.&lt;br&gt;
- &lt;em&gt;The Man Versus the State&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This work went on to inspire an ideology that we know today as &amp;ldquo;Social Darwinism&amp;rdquo;, which is ironically named since it is neither social nor Darwinist. It&amp;rsquo;s a revolting and disdainful ideology, one that belongs, in the words of journalist &lt;a class=&#34;link&#34; href=&#34;https://philosophicalvegan.com/viewtopic.php?f=17&amp;amp;t=3186&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Robert Wright&lt;/a&gt;, &amp;ldquo;in the dustbin of intellectual history&amp;rdquo;. I think that&amp;rsquo;s a suitable fate for it.&lt;/p&gt;
&lt;p&gt;Coming back to Spencer.&lt;/p&gt;
&lt;p&gt;In committing this mistake - this &amp;ldquo;naturalistic fallacy&amp;rdquo; - the idea that morality and ethics can be derived from nature, he ended up providing the ethics equivalent of a blank check to the capitalists.&lt;/p&gt;
&lt;p&gt;As the 19th century (and the Industrial Revolution) chugged along, Spencer&amp;rsquo;s writings ended up being used to justify laissez-faire economics, war, racism and various heinous political doctrines. It justified the power of capitalists because they where the fittest according to themselves.&lt;/p&gt;
&lt;p&gt;However, these ideas pre-date and commonly contradict Darwin&amp;rsquo;s ideas, and indeed their proponents rarely invoked Darwin in support.&lt;/p&gt;
&lt;p&gt;This is all wrong of course. For instance, many species aren&amp;rsquo;t strong on their own, but still thrive because they &lt;strong&gt;cooperate&lt;/strong&gt;. Humans are pretty weak. Our children are a huge burden on the parents before they grow up. We&amp;rsquo;re not fast, and neither can we outrun most predators. Most people can&amp;rsquo;t even outrun a &lt;strong&gt;chicken&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A single human is unlikely to thrive. But because we have community and care for each other we managed to succeed as species.&lt;/p&gt;
&lt;h2 id=&#34;darwins-biggest-mistake&#34;&gt;Darwin&amp;rsquo;s Biggest Mistake&lt;/h2&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Alfred_Russel_Wallace&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Alfred Russel Wallace&lt;/a&gt; suggested Darwin to use the words &amp;ldquo;survival of the fittest&amp;rdquo; as an alternative to &amp;ldquo;natural selection&amp;rdquo;. He caved.&lt;/p&gt;
&lt;p&gt;In 1868, Darwin used the phrase in &lt;em&gt;The Variation of Animals and Plants under Domestication&lt;/em&gt;., going so far as to even call it a &amp;ldquo;bad term&amp;rdquo;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This preservation, during the battle for life, of varieties which possess any advantage in structure, constitution, or instinct, I have called Natural Selection; and Mr. Herbert Spencer has well expressed the same idea by the Survival of the Fittest. The term &amp;rsquo;natural selection&amp;rsquo; is in some respects a bad one, as it seems to imply conscious choice; but this will be disregarded after a little familiarity &lt;br&gt;
- &lt;em&gt;The Variation of Animals and Plants under Domestication&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the 1869 (5&lt;sup&gt;th&lt;/sup&gt; Edition) of &lt;em&gt;On The Origin of Species&lt;/em&gt;, Darwin changed it from
&amp;ldquo;Natural Selection&amp;rdquo; to &amp;ldquo;Natural Selection, or the Survival of the Fittest&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;closing-thoughts&#34;&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;Stephen Jay Gould (in Life is Beautiful) points out that the survival of a species at a certain time only reflects its fitness at that point in time, and not an absolute value of fitness, which doesn&amp;rsquo;t exist: there are plenty of genes (or even species) that disappeared for a reason or another, but would be a better fit for today&amp;rsquo;s conditions than the ones who survived, if they were still here.&lt;/p&gt;
&lt;p&gt;Therefore seeing evolution as a continuous improvement of a gene pool towards evergrowing fitness is a misconception anyway. This is why eugenics and the people who bandy it about miss the point, or the randomness of it all. As well as the loooooong timelines and odd (but incredibly egoistic) idea that the most intelligent thing life has produced is somehow stupid compared to imaginary things us stupid things created in our minds.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-10-31-cult-of-not-done/&#34; &gt;The Cult of Not Done Manifesto&lt;/a&gt;&lt;br&gt;
If you’re intrigued by the idea of challenging traditional concepts and exploring the depths of continuous evolution, the “Cult of Not Done Manifesto” offers a fresh perspective on progress and perfection that complements the critical examination of misunderstood evolutionary theories you’ve just read about.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-04-addendum-webfinger/&#34; &gt;Addendum: What&#39;s a Webfinger?&lt;/a&gt;&lt;br&gt;
Exploring the evolution of digital ecosystems, just like natural ones, can reveal how technologies like Webfinger are adapting to make online communities more interconnected and user-friendly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-01-linux-ip-geolocation-list/&#34; &gt;Get frequency distribution of countries in a list of newline separated IP addresses in Linux&lt;/a&gt;&lt;br&gt;
Switching gears from the evolution of ideas to the evolution of technology, you’ll find the practical guide on mapping IP addresses to countries fascinating as it showcases how data analysis techniques can uncover patterns in our digital ecosystem.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Addendum: What&#39;s a Webfinger?</title>
        <link>https://ishan.page/blog/2023-07-04-addendum-webfinger/</link>
        <pubDate>Tue, 04 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-04-addendum-webfinger/</guid>
        <description>&lt;p&gt;Following an interesting discussion on &lt;a class=&#34;link&#34; href=&#34;https://programming.dev/post/375331&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;programming.dev&lt;/a&gt; after the &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-02-well-known&#34; &gt;last article&lt;/a&gt;, I thought it would be good to add some extra notes regarding Webfinger.&lt;/p&gt;
&lt;p&gt;Webfinger provides a standard API for discovering the user profile details and avatar from the username, no matter the software running on the node. The standard Webfinger endpoint is &lt;code&gt;/.well-known/webfinger&lt;/code&gt;. It must always be queried with at least the resource.&lt;/p&gt;
&lt;p&gt;Some examples using my account  on Lemmy (programming.dev) and Mastodon (hachyderm.io):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ curl https://programming.dev/.well-known/webfinger&lt;span class=&#34;se&#34;&gt;\?&lt;/span&gt;resource&lt;span class=&#34;se&#34;&gt;\=&lt;/span&gt;acct:ishanpage@programming.dev &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;subject&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;acct:ishanpage@programming.dev&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://webfinger.net/rel/profile-page&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://programming.dev/u/ishanpage&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;self&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;application/activity+json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://programming.dev/u/ishanpage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;https://www.w3.org/ns/activitystreams#type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Person&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl https://hachyderm.io/.well-known/webfinger&lt;span class=&#34;se&#34;&gt;\?&lt;/span&gt;resource&lt;span class=&#34;se&#34;&gt;\=&lt;/span&gt;acct:ishands@hachyderm.io &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;subject&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;acct:ishands@hachyderm.io&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;aliases&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://hachyderm.io/@ishands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://hachyderm.io/users/ishands&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://webfinger.net/rel/profile-page&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;text/html&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://hachyderm.io/@ishands&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;self&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;application/activity+json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://hachyderm.io/users/ishands&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;rel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://ostatus.org/schema/1.0/subscribe&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;template&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://hachyderm.io/authorize_interaction?uri={uri}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;While I&amp;rsquo;m not sure &lt;em&gt;exactly&lt;/em&gt; how this is useful, my assumption is that it&amp;rsquo;s useful during federation, and for generic activitypub clients because different Fediverse software maps usernames and profiles differently.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-02-well-known/&#34; &gt;The secret life of .well-known&lt;/a&gt;&lt;br&gt;
Unravel the secrets of the web’s hidden directories and discover how they power up your favorite online spaces, from secure email setups to finding your next favorite fediverse platform.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;Read This Next: Using AI For Recommending Posts On My Blog&lt;/a&gt;&lt;br&gt;
Exploring how Webfinger revolutionizes user discovery in the fediverse, you’ll be intrigued by how AI-driven recommendations can similarly transform your content exploration with smarter, more personalized suggestions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
Explore how to harness the power of APIs further by learning to extract valuable data from Facebook Lead Ads, just like you discovered the potential of Webfinger for user discovery across platforms.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>The secret life of .well-known</title>
        <link>https://ishan.page/blog/2023-07-02-well-known/</link>
        <pubDate>Sun, 02 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-02-well-known/</guid>
        <description>&lt;p&gt;My first encounter with the &lt;code&gt;.well-known&lt;/code&gt; directory was when Let&amp;rsquo;s Encrypt first hit the scene and I was learning about VPS-es and how Linux on the server worked.&lt;/p&gt;
&lt;p&gt;I noticed that it used certain URLs like &lt;code&gt;.well-known/acme-challenge/3d2f4b8c9d0a4f8b9e6f7d8c9e0a4f8b&lt;/code&gt;. This led me down a nice rabbit hole about the ACME protocol, but that&amp;rsquo;s a story for another time.&lt;/p&gt;
&lt;p&gt;Years later, when configuring servers to use paid HTTPs certificates, I noticed the use of the &lt;code&gt;.well-known/pki-validation/&lt;/code&gt; directory for verifying certificates. I filed this knowledge away in my brain as &amp;ldquo;the &lt;code&gt;.well-known&lt;/code&gt; directory is for SSL related stuff&amp;rdquo; and continued on with my life.&lt;/p&gt;
&lt;p&gt;Somewhere in the middle, I noticed that a lot of brute force attacks on servers I monitored would be directed to &lt;code&gt;.well-known&lt;/code&gt; URLs. At that point, I had learned about DNS based verification, and quickly moved on from HTTP challenges, and blocked access to the directory in my web server configs. I made this a part of my base setup on every server, and didn&amp;rsquo;t really think too much about the directory any more.&lt;/p&gt;
&lt;p&gt;That was, until &lt;em&gt;very&lt;/em&gt; recently.&lt;/p&gt;
&lt;h2 id=&#34;the-fiasco-with-nodeinfo&#34;&gt;The Fiasco with NodeInfo&lt;/h2&gt;
&lt;p&gt;As a recent migrant to the Fediverse after the Reddit API changes shut down my 3rd party app of choice, I joined a fairly interesting Lemmy instance, and I quickly found the distributed nature fascinating. All I could think about was: &amp;ldquo;I want to see a giant map of all the instances and who is connected to who&amp;rdquo;, and immediately set out to create a web scraper that could gather this information for me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&amp;rsquo;t worry, I made sure to respect &lt;code&gt;robots.txt&lt;/code&gt; for every site the scraper visited.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lemmy&amp;rsquo;s API documentation is fairly poor, and I flailed for quite a while before I discovered the endpoint (&lt;code&gt;/api/v3/site&lt;/code&gt;) that would give me the list of federated servers.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s when I realized, that Lemmy could &lt;em&gt;and did&lt;/em&gt; federate with other Fediverse software like Mastodon, Calckey, Pleroma, WriteFreely, PixelFed and more. And each one of these have different APIs and different endpoints that would give me the data I need.&lt;/p&gt;
&lt;p&gt;I needed a way to detect which software each server was running. My first instinct was to use some sort of heuristic, but that&amp;rsquo;s unreliable, so I continued researching and discovered the &lt;a class=&#34;link&#34; href=&#34;https://github.com/jhass/nodeinfo/blob/main/PROTOCOL.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;NodeInfo&lt;/a&gt; protocol.&lt;/p&gt;
&lt;p&gt;And wouldn&amp;rsquo;t you have it, the resource I need to request &lt;em&gt;just happens to be&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/.well-known/nodeinfo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;At this point, my curiousity was piqued. There was more to this &lt;code&gt;.well-known&lt;/code&gt; directory than I had initially thought!&lt;/p&gt;
&lt;h2 id=&#34;the-rfc-enters-the-fray&#34;&gt;The RFC enters the fray&lt;/h2&gt;
&lt;p&gt;It &lt;a class=&#34;link&#34; href=&#34;https://serverfault.com/questions/795467/what-is-the-purpose-of-the-well-known-folder&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;turns out&lt;/a&gt;, that the .well-known directory is defined in &lt;a class=&#34;link&#34; href=&#34;https://www.rfc-editor.org/rfc/rfc8615&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;RFC 8615&lt;/a&gt;. The intention seems to be to make it like a generic and extendable version of &lt;code&gt;robots.txt&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is increasingly common for Web-based protocols to require the discovery of policy or other information about a host (&amp;ldquo;site-wide metadata&amp;rdquo;) before making a request. For example, the Robots Exclusion Protocol &lt;a class=&#34;link&#34; href=&#34;http://www.robotstxt.org/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://www.robotstxt.org/&lt;/a&gt; specifies a way for automated processes to obtain permission to access resources; likewise, the Platform for Privacy Preferences [W3C.REC-P3P-20020416] tells user-agents how to discover privacy policy beforehand.&lt;/p&gt;
&lt;p&gt;While there are several ways to access per-resource metadata (e.g., HTTP headers, WebDAV&amp;rsquo;s PROPFIND [RFC4918]), the perceived overhead (either in terms of client-perceived latency and/or deployment difficulties) associated with them often precludes their use in these scenarios.&lt;/p&gt;
&lt;p&gt;When this happens, it is common to designate a &amp;ldquo;well-known location&amp;rdquo; for such data, so that it can be easily located. However, this approach has the drawback of risking collisions, both with other such designated &amp;ldquo;well-known locations&amp;rdquo; and with pre-existing resources.&lt;/p&gt;
&lt;p&gt;To address this, this memo defines a path prefix in HTTP(S) URIs for these &amp;ldquo;well-known locations&amp;rdquo;, /.well-known/. Future specifications that need to define a resource for such site-wide metadata can register their use to avoid collisions and minimise impingement upon sites&amp;rsquo; URI space.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&amp;rsquo;s a whole &lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/w/index.php?title=Well-known_URI#List_of_well-known_URIs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;bunch&lt;/strong&gt; of stuff&lt;/a&gt; that you can do with stuff in the &lt;code&gt;.well-known&lt;/code&gt; folder, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.hardill.me.uk/wordpress/2021/01/24/email-autoconfiguration/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Automate email client configuration for self hosted email&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://web.dev/change-password-url/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Let password managers automatically know which URL to visit to change a password&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://platform.openai.com/docs/plugins/getting-started&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Let ChatGPT discover your plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://spec.matrix.org/latest/client-server-api/#well-known-uri&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Discover Matrix server details&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and of course, let&amp;rsquo;s not forget about &lt;a class=&#34;link&#34; href=&#34;https://webfinger.net/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Webfinger&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“A webfinger? Is that what I use to poke someone on Facebook?” - Anonymous&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2023-07-04&lt;/strong&gt;: I have published a follow-up - &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-04-addendum-webfinger&#34; &gt;Addendum: Webfinger&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2023-07-07&lt;/strong&gt;: This article was featured in &lt;a class=&#34;link&#34; href=&#34;https://tldr.tech/tech/2023-07-07&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;tldr.tech&lt;/a&gt;, and as of time of writing I have had over 6500 hits on this post. I am overwhelmed and moved by this, and by all the positive comments I have received. I never imagined that my little blog would ever be read by so many people.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-04-addendum-webfinger/&#34; &gt;Addendum: What&#39;s a Webfinger?&lt;/a&gt;&lt;br&gt;
Explore how Webfinger seamlessly connects the dots between users across the fediverse, building on the foundational role of the .well-known directory you just learned about.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-09-15-eleventy-deploy-github-sftp/&#34; &gt;Build and Deploy Eleventy via SFTP using Github Actions&lt;/a&gt;&lt;br&gt;
Unlock the power of automation for your Eleventy projects with GitHub Actions, streamlining your deployment process and saving you time for more creative coding endeavors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-01-linux-ip-geolocation-list/&#34; &gt;Get frequency distribution of countries in a list of newline separated IP addresses in Linux&lt;/a&gt;&lt;br&gt;
Exploring the nuts and bolts of web technology? This guide on mapping IP addresses to countries using Linux commands could be your next step in understanding the digital world’s geography.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Get frequency distribution of countries in a list of newline separated IP addresses in Linux</title>
        <link>https://ishan.page/blog/2023-07-01-linux-ip-geolocation-list/</link>
        <pubDate>Sat, 01 Jul 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-07-01-linux-ip-geolocation-list/</guid>
        <description>&lt;p&gt;Assuming that the IP addresses are in a file called &lt;code&gt;list.txt&lt;/code&gt; in a format such as below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;104.28.29.66
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;92.40.175.51
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;116.255.32.201
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;91.150.51.170
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;108.167.20.103
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5.187.159.175
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;166.198.250.121
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;74.78.184.213
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;A prerequisite for this is the &lt;code&gt;geoiplookup&lt;/code&gt; command, which is available in the &lt;code&gt;geoip-bin&lt;/code&gt; package on most distros.&lt;/p&gt;
&lt;p&gt;Run the following command to get the frequency distribution:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat list.txt &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xargs -n &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; geoiplookup &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sed &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/GeoIP Country Edition: //g&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sort &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; uniq -c &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sort -r
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This will give you an output as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    462 US, United States
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    124 DE, Germany
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     62 CA, Canada
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     47 GB, United Kingdom
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     34 AU, Australia
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     31 NL, Netherlands
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     23 FR, France
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     19 IN, India
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     18 SE, Sweden
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     14 FI, Finland
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     10 BE, Belgium
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      9 NO, Norway
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      9 IT, Italy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      9 BR, Brazil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      7 SG, Singapore
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      7 PT, Portugal
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      7 IL, Israel
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      7 CH, Switzerland
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      7 AT, Austria
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      6 IR, Iran, Islamic Republic of
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-24-docker-container-network-ip/&#34; &gt;Get Docker Containers running in a particular network&lt;/a&gt;&lt;br&gt;
Unlock the power of your network by learning how to effortlessly identify and organize running Docker containers, just like you mastered mapping IP addresses to countries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2014-10-09-mpb-scraper-postmortem/&#34; &gt;Scraping the MPB website - A Postmortem&lt;/a&gt;&lt;br&gt;
Uncover the trials and triumphs of data extraction as you journey from mapping IP geolocations to wrestling with web scraping challenges, learning from real-world tech adventures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-04-15-php-inline-lists/&#34; &gt;3 ways to render inline lists in PHP&lt;/a&gt;&lt;br&gt;
Unravel the art of data manipulation further by exploring how PHP can streamline your list processing tasks, just as you’ve mastered geographical data analysis with Linux commands.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Get Docker Containers running in a particular network</title>
        <link>https://ishan.page/blog/2023-06-24-docker-container-network-ip/</link>
        <pubDate>Sat, 24 Jun 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-06-24-docker-container-network-ip/</guid>
        <description>&lt;p&gt;The following script can be used to start list the running containers inside a particular network along with their ips.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#! /usr/bin/zsh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Image\tHostname\tIP&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; N in &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;docker ps -q&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;docker inspect -f &lt;span class=&#34;s1&#34;&gt;&amp;#39;{{.Config.Image}}\t{{ .Config.Hostname }}\t&amp;#39;&lt;/span&gt; &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;docker inspect -f &lt;span class=&#34;s1&#34;&gt;&amp;#39;{{range $i, $value := .NetworkSettings.Networks}}{{if eq $i &amp;#34;custom_network_name&amp;#34;}}{{.IPAddress}}{{end}}{{end}}&amp;#39;&lt;/span&gt; &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Usage example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./network-hosts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Bonus tip:&lt;br&gt;
Pipe the output into &lt;code&gt;column -t&lt;/code&gt; like so to get a pretty formatted tabular output.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./network-hosts | column -t
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-22-docker-start-in-network/&#34; &gt;Start a container in a particular docker network&lt;/a&gt;&lt;br&gt;
Unlock the full potential of your Docker setup by learning how to not only list all running containers on your network but also how to effortlessly start new ones with customized settings!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-01-linux-ip-geolocation-list/&#34; &gt;Get frequency distribution of countries in a list of newline separated IP addresses in Linux&lt;/a&gt;&lt;br&gt;
Unlock the power of IP analysis by learning how to map the global footprint of your Docker containers, enhancing your network insights and security strategies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-21-linux-use-multiple-git-profiles/&#34; &gt;Using different Github accounts with different private keys on Linux&lt;/a&gt;&lt;br&gt;
Just like you streamlined your Docker workflow with a zsh script, you can similarly optimize your GitHub setup across multiple accounts with some clever SSH configurations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Parsing single level yaml files into a Lua table</title>
        <link>https://ishan.page/blog/2023-06-23-lua-yaml-dict/</link>
        <pubDate>Fri, 23 Jun 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-06-23-lua-yaml-dict/</guid>
        <description>&lt;p&gt;Given a yaml-like file containing key-value pairs like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;key1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;value1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;key2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;value2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;key3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;value3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The following function will load it and return the data as a Lua table.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read_yaml_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;io.open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;r&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Failed to open file: &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lines&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;(%w+):%s*(.+)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Exploring how I tackled HTML generation with jq might spark new ideas for you, especially if you enjoy learning about creative uses of tools outside their typical applications, similar to parsing YAML with Lua.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
Unlock the power of data handling across different languages by learning how to seamlessly integrate Facebook Lead Ads data into your Python projects, just like you managed YAML files in Lua.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-05-08-windows-xampp-postgres/&#34; &gt;Install Postgres into XAMPP on Windows&lt;/a&gt;&lt;br&gt;
After mastering YAML parsing in Lua, expanding your development environment with Postgres integration in XAMPP could be your next big leap in building robust applications.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Start a container in a particular docker network</title>
        <link>https://ishan.page/blog/2023-06-22-docker-start-in-network/</link>
        <pubDate>Thu, 22 Jun 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-06-22-docker-start-in-network/</guid>
        <description>&lt;p&gt;The following script can be used to start a container inside a particular network.&lt;/p&gt;
&lt;p&gt;Usage example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./start-in-network redis
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./start-in-network vad1mo/hello-world-rest 5050
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/usr/bin/zsh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$#&lt;/span&gt; -eq &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;syntax: ./start-in-network container-name [container port binding]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;You must provide at least container name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;docker_container_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$#&lt;/span&gt; -eq &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;docker_container_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;docker run -d &lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;docker_container_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;docker run -d -p &lt;span class=&#34;nv&#34;&gt;$2&lt;/span&gt;:&lt;span class=&#34;nv&#34;&gt;$2&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker network connect custom_network_name docker_container_id
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-24-docker-container-network-ip/&#34; &gt;Get Docker Containers running in a particular network&lt;/a&gt;&lt;br&gt;
After learning how to kickstart your Docker containers, discovering how to neatly list and manage them can streamline your workflow even further.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-05-08-windows-xampp-postgres/&#34; &gt;Install Postgres into XAMPP on Windows&lt;/a&gt;&lt;br&gt;
After mastering Docker container setups, taking your local development environment to the next level with Postgres and XAMPP integration could be your next big win.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-05-natural-selection-misconceptions/&#34; &gt;On &amp;quot;Natural Selection&amp;quot; and &amp;quot;Survival of the fittest&amp;quot;&lt;/a&gt;&lt;br&gt;
Explore how misconceptions can shape our understanding and applications, from Docker networks to Darwin’s theories, revealing the importance of clarity and accuracy in every field.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Using different Github accounts with different private keys on Linux</title>
        <link>https://ishan.page/blog/2023-06-21-linux-use-multiple-git-profiles/</link>
        <pubDate>Wed, 21 Jun 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-06-21-linux-use-multiple-git-profiles/</guid>
        <description>&lt;p&gt;Create a file &lt;code&gt;~/.ssh/config&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you have 2 keys, for example: &lt;code&gt;id_rsa&lt;/code&gt; for your personal, and &lt;code&gt;id_work&lt;/code&gt; for your work, set the config as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Host github-work
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    HostName github.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    IdentityFile ~/.ssh/id_work
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    IdentitiesOnly yes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now, when cloning or adding remote, change the &lt;code&gt;github.com&lt;/code&gt; in the clone url is changed to &lt;code&gt;github-work&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone git@github-work:username/whatever.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-09-18-pem-linux/&#34; &gt;Generate PEM file for any Linux user&lt;/a&gt;&lt;br&gt;
Unlock the full potential of secure, passwordless connections by mastering the creation of a 4096-bit RSA key pair, a perfect next step after setting up your multiple GitHub accounts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-11-28-bashrc-oopsie-deleted/&#34; &gt;Accidentally deleted your .bashrc?&lt;/a&gt;&lt;br&gt;
After mastering multiple GitHub accounts with SSH keys, learning to tweak your .bashrc file could be your next step to becoming a Linux power user.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-10-15-systemd-discord-notify/&#34; &gt;Discord Notifications from Systemd&lt;/a&gt;&lt;br&gt;
After mastering multiple GitHub accounts with SSH keys, you’ll love learning how to keep tabs on your services with Discord notifications, making your workflow smoother and more connected.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API</title>
        <link>https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/</link>
        <pubDate>Tue, 20 Jun 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/</guid>
        <description>&lt;p&gt;Given two unix timestamps, this Python script fetches all the leads received by a particular Facebook Lead Ads form using the Facebook v14 Graph API.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Constants&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;YOUR_ACCESS_TOKEN&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;LIMIT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;FROM_TIMESTAMP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1678613400&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UPTO_TIMESTAMP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1678704000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;FORM_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;12341241244&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;create_api_url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;form_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;https://graph.facebook.com/v14.0/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;form_id&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/leads&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;filter_tpl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;field&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;time_created&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;operator&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;GREATER_THAN&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;field&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;time_created&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;operator&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;LESS_THAN&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s2&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dumps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;do_query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;form_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;url&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_api_url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;form_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;querystring&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LIMIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;filtering&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter_tpl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;querystring&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;do_query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FORM_ID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FROM_TIMESTAMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UPTO_TIMESTAMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2014-10-09-mpb-scraper-postmortem/&#34; &gt;Scraping the MPB website - A Postmortem&lt;/a&gt;&lt;br&gt;
Unlock the secrets of data extraction with a real-world tale of triumph and trial, as you explore how overcoming challenges in web scraping can sharpen your coding skills and strategy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recommended reading not found for slug or filename: &#39;post/power-digits-log-formula-trick&#39;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-10-15-systemd-discord-notify/&#34; &gt;Discord Notifications from Systemd&lt;/a&gt;&lt;br&gt;
If you’re keen on automating tasks and notifications, learning how to send Discord alerts for your system’s service statuses could be a slick addition to your toolkit, especially after tackling Facebook API integrations.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Hello World</title>
        <link>https://ishan.page/blog/2023-06-20-hello-world/</link>
        <pubDate>Tue, 20 Jun 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-06-20-hello-world/</guid>
        <description>&lt;p&gt;Many people who know me ask me why I haven&amp;rsquo;t got a personal website or blog. I often don&amp;rsquo;t know what to tell them. It&amp;rsquo;s certainly not for a lack of trying.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s one of the very first blogs I started to help my 7th grade classmates learn programming which they weren&amp;rsquo;t able to understand in school:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/blog/2023-06-20-hello-world/qbasic-site-screenshot.png&#34;
	width=&#34;985&#34;
	height=&#34;744&#34;
	srcset=&#34;https://ishan.page/blog/2023-06-20-hello-world/qbasic-site-screenshot_hu57fe8d6c6e138f4d26ba7d15d40d6476_172726_480x0_resize_box_3.png 480w, https://ishan.page/blog/2023-06-20-hello-world/qbasic-site-screenshot_hu57fe8d6c6e138f4d26ba7d15d40d6476_172726_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Screenshot of my first blog&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;132&#34;
		data-flex-basis=&#34;317px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;I fumbled around various other blogs, but never managed to be able to post consistently. I was either too lazy, having other things going on in life, or just plain scared that people would judge me. (this also explains why my &lt;a class=&#34;link&#34; href=&#34;https://github.com/sad-pixel/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;github&lt;/a&gt; is so sparse, but I plan to change that soon)&lt;/p&gt;
&lt;p&gt;I  settled for having a sweet and simple landing page, based on a theme from HTML5Up:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/blog/2023-06-20-hello-world/landing-page-screenshot.png&#34;
	width=&#34;872&#34;
	height=&#34;600&#34;
	srcset=&#34;https://ishan.page/blog/2023-06-20-hello-world/landing-page-screenshot_hu6d07e2d8a0f6dd939011905bf65245cb_177610_480x0_resize_box_3.png 480w, https://ishan.page/blog/2023-06-20-hello-world/landing-page-screenshot_hu6d07e2d8a0f6dd939011905bf65245cb_177610_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Screenshot of my landing page&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;145&#34;
		data-flex-basis=&#34;348px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;While decidedly amateurish and minimal, it&amp;rsquo;s also woefully out of date (I last used VueJS in 2019). So, it&amp;rsquo;s time for a refresh.&lt;/p&gt;
&lt;h2 id=&#34;goals-and-wishes&#34;&gt;Goals and wishes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rescue old blog posts from whatever previous blogs I have in my backups and post them here&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;Projects&amp;rdquo; section where I can post my projects and project related writeups&lt;/li&gt;
&lt;li&gt;Have fun indieweb and fediverse things&lt;/li&gt;
&lt;li&gt;Add a proper RSS feed and webmentions support&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;Grimoire&amp;rdquo; where I can post code snippets and quick explainers for my future self&lt;/li&gt;
&lt;li&gt;Semi-regular blog posting frequency (fingers crossed!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Is this an ambitious list? Probably. But that&amp;rsquo;s okay. Let&amp;rsquo;s see how it goes. I&amp;rsquo;m excited to see what the future holds for me.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/&#34; &gt;Blogging with Jupyter Notebooks in Hugo&lt;/a&gt;&lt;br&gt;
Discover how embracing Jupyter notebooks transformed my blogging workflow, a change that could inspire and streamline your own website revamp.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2014-09-07-gamedev-ideas/&#34; &gt;Gamedev Ideas&lt;/a&gt;&lt;br&gt;
Explore how my journey from web development woes to game design dreams can inspire your own creative revival.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-10-31-cult-of-not-done/&#34; &gt;The Cult of Not Done Manifesto&lt;/a&gt;&lt;br&gt;
Embrace the beauty of the unfinished; the “Cult of Not Done Manifesto” might just be the motivational nudge you need to keep evolving your website without the pressure of perfection.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Fix WSL time drift</title>
        <link>https://ishan.page/blog/2023-03-08-wsl-time-drift/</link>
        <pubDate>Wed, 08 Mar 2023 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2023-03-08-wsl-time-drift/</guid>
        <description>&lt;p&gt;There is a bug in WSL2 that causes the clock inside the VM to drift behind the actual clock on the machine.&lt;/p&gt;
&lt;p&gt;This can lead to many unexpected issues, ranging from harmless (git commit messages having old timestamps) to
severe (SSL connection failures).&lt;/p&gt;
&lt;p&gt;We can sync the VM clock using the command&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo hwclock -s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;We can also add the command as a cron job every 5-10 minutes to make sure that the clock doesn&amp;rsquo;t drift too far back.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-26-use-the-flags-luke/&#34; &gt;Dear past me, use the flags&lt;/a&gt;&lt;br&gt;
After tackling the technical hiccup of syncing VM clocks in WSL2, you’ll appreciate the wisdom in learning from past mistakes to avoid future headaches, like the crucial need for update mechanisms and version control in software development.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2021-09-18-pem-linux/&#34; &gt;Generate PEM file for any Linux user&lt;/a&gt;&lt;br&gt;
After fixing your WSL2 clock bug, securing your SSH connections with a robust 4096-bit RSA key is the next smart move to enhance your system’s security and efficiency.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-24-docker-container-network-ip/&#34; &gt;Get Docker Containers running in a particular network&lt;/a&gt;&lt;br&gt;
After tackling WSL2’s time-sync bug, you’ll appreciate streamlining your Docker workflow with a handy zsh script to monitor your containers efficiently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>About</title>
        <link>https://ishan.page/about/</link>
        <pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/about/</guid>
        <description>&lt;h2 id=&#34;hi-there-im-ishan&#34;&gt;Hi There, I&amp;rsquo;m Ishan.&lt;/h2&gt;
&lt;p&gt;I was fascinated by coding from a young age. I taught myself how to code from the ground up, and I have never stopped learning and exploring new possibilities.&lt;/p&gt;
&lt;p&gt;Over the past ten years, I have worked on various projects that challenged me to grow as a coder and a problem-solver. I have learned how to build software that is reliable, scalable and performant, and that serves the needs of millions of users.&lt;/p&gt;
&lt;p&gt;Thank you for visiting my blog, where I share my journey, thoughts, and experiences with you. I hope you find something useful and inspiring here.&lt;/p&gt;
&lt;p&gt;Currently, I am working on DDoS mitigation systems at Asians Group LLC. I have previously worked on systems and websites using OpenCV, Python, Django, PHP, Laravel, Vue, Eleventy, and many others.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also finally working towards a Bachelor&amp;rsquo;s Degree in Data Science and Applications from the &lt;a class=&#34;link&#34; href=&#34;https://study.iitm.ac.in/ds/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Indian Institute of Technology, Madras&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The beautiful photo was taken by my friend Sabyasachi Das in scenic Pondicherry, India.&lt;/p&gt;
&lt;h2 id=&#34;featured-in&#34;&gt;Featured In&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://ishan.page/about/tldr.png&#34;
	width=&#34;343&#34;
	height=&#34;150&#34;
	srcset=&#34;https://ishan.page/about/tldr_hu684d9c19f6258d1c831886ae2ebb4c39_14272_480x0_resize_box_3.png 480w, https://ishan.page/about/tldr_hu684d9c19f6258d1c831886ae2ebb4c39_14272_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;TLDR Newsletter&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;228&#34;
		data-flex-basis=&#34;548px&#34;
	
&gt; &lt;img src=&#34;https://ishan.page/about/vshn.png&#34;
	width=&#34;365&#34;
	height=&#34;138&#34;
	srcset=&#34;https://ishan.page/about/vshn_hu420182729c4c3453ab24ba812740cd54_3380_480x0_resize_box_3.png 480w, https://ishan.page/about/vshn_hu420182729c4c3453ab24ba812740cd54_3380_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;VSHN Timer&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;264&#34;
		data-flex-basis=&#34;634px&#34;
	
&gt; &lt;img src=&#34;https://ishan.page/about/eisamay.png&#34;
	width=&#34;205&#34;
	height=&#34;105&#34;
	srcset=&#34;https://ishan.page/about/eisamay_hu7474e9c0d7de2c03696561e938275a7a_4345_480x0_resize_box_3.png 480w, https://ishan.page/about/eisamay_hu7474e9c0d7de2c03696561e938275a7a_4345_1024x0_resize_box_3.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Ei Samay&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;195&#34;
		data-flex-basis=&#34;468px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;about-this-website&#34;&gt;About This Website&lt;/h2&gt;
&lt;p&gt;This website is the latest iteration &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-hello-world/&#34; &gt;of many&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;faqs&#34;&gt;FAQs&lt;/h2&gt;
&lt;h3 id=&#34;how-do-you-deal-with-bugs-that-just-wont-budge-do-you-bribe-them&#34;&gt;How do you deal with bugs that just won’t budge? Do you bribe them?&lt;/h3&gt;
&lt;p&gt;Yep, you caught me. I bribe them. I&amp;rsquo;m dirty.&lt;/p&gt;
&lt;h3 id=&#34;do-you-have-a-secret-coding-dance-that-boosts-productivity&#34;&gt;Do you have a secret coding dance that boosts productivity?&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s more of a secret keyboard rhythm that syncs perfectly with the code’s heartbeat. Sadly, no dance moves&amp;hellip; yet.&lt;/p&gt;
&lt;h3 id=&#34;how-do-you-manage-to-stay-sane-during-those-long-debugging-sessions&#34;&gt;How do you manage to stay sane during those long debugging sessions?&lt;/h3&gt;
&lt;p&gt;Insanity is relative! But seriously, music, memes, and the occasional staring contest with the screen keep me going.&lt;/p&gt;
&lt;h3 id=&#34;how-can-i-subscribe-to-updates-from-your-site&#34;&gt;How can I subscribe to updates from your site?&lt;/h3&gt;
&lt;p&gt;You can subscribe to updates &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/feeds/blog/&#34; &gt;via RSS&lt;/a&gt; or you could subscribe to the &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/newsletter/&#34; &gt;newsletter&lt;/a&gt; instead.&lt;/p&gt;
&lt;h3 id=&#34;what-did-you-use-to-make-this-website&#34;&gt;What did you use to make this website?&lt;/h3&gt;
&lt;p&gt;This website is made with Hugo, using the excellent &lt;a class=&#34;link&#34; href=&#34;https://stack.jimmycai.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Stack&lt;/a&gt; theme with my own &lt;a class=&#34;link&#34; href=&#34;https://github.com/sad-pixel/hugo-theme-stack/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;customizations&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;what-other-blogs-do-you-like&#34;&gt;What other blogs do you like?&lt;/h3&gt;
&lt;p&gt;Too many to list! Maybe one day I will try to collate them.&lt;/p&gt;
&lt;h3 id=&#34;what-is-the-best-programming-language&#34;&gt;What is the best programming language?&lt;/h3&gt;
&lt;p&gt;Haskell, obviously.&lt;/p&gt;
&lt;h3 id=&#34;is-it-true-youve-had-staring-contests-with-your-code-who-won&#34;&gt;Is it true you&amp;rsquo;ve had staring contests with your code? Who won?&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s a tie between me and the code; we both blinked and then had to debug why.&lt;/p&gt;
&lt;h3 id=&#34;do-you-believe-in-horoscopes&#34;&gt;Do you believe in horoscopes?&lt;/h3&gt;
&lt;p&gt;Absolutely! My horoscope for today: &amp;ldquo;You will encounter a syntax error, but fear not, for the solution is just a semicolon away!&amp;rdquo;&lt;/p&gt;
&lt;h3 id=&#34;why-do-you-hate-spas&#34;&gt;Why do you hate SPAs?&lt;/h3&gt;
&lt;p&gt;I don&amp;rsquo;t necessarily hate SPAs - I just believe there is a right and a wrong time to SPA.&lt;/p&gt;
&lt;h3 id=&#34;why-do-you-hate-javascript&#34;&gt;Why do you hate Javascript?&lt;/h3&gt;
&lt;p&gt;Ecosystem catch-up overload. I don&amp;rsquo;t hate Javascript - but it&amp;rsquo;s hard to keep up with all the happenings.&lt;/p&gt;
&lt;h2 id=&#34;elsewhere&#34;&gt;Elsewhere&lt;/h2&gt;
</description>
        </item>
        <item>
        <title>Articles</title>
        <link>https://ishan.page/blog/</link>
        <pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/</guid>
        <description></description>
        </item>
        <item>
        <title>Discord Notifications from Systemd</title>
        <link>https://ishan.page/blog/2021-10-15-systemd-discord-notify/</link>
        <pubDate>Fri, 15 Oct 2021 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2021-10-15-systemd-discord-notify/</guid>
        <description>&lt;p&gt;Add the following lines in your service definition file (&lt;code&gt;/etc/systemd/system/service_xyz.service&lt;/code&gt;) in the &lt;code&gt;[Service]&lt;/code&gt; section:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ExecStartPost=/home/service_xyz/hooks.sh start
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ExecStopPost=/home/service_xyz/hooks.sh stop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In &lt;code&gt;/home/service_xyz/hooks.sh&lt;/code&gt;, put&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;hook_url&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;https://discord.com/api/webhooks/xxxxxxxxxxxx/yyyyyyyyyy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; start&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  curl -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Content-type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  -X POST -d &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;s1&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    &amp;#34;content&amp;#34;:&amp;#34;Hook: &amp;lt;NAME&amp;gt;; Action Start&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  }&amp;#39;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$hook_url&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; stop&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  curl -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Content-type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  -X POST -d &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;s1&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    &amp;#34;content&amp;#34;:&amp;#34;Hook: &amp;lt;NAME&amp;gt;; Action Stop&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  }&amp;#39;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$hook_url&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;   
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-02-well-known/&#34; &gt;The secret life of .well-known&lt;/a&gt;&lt;br&gt;
Exploring the .well-known directory’s vast applications can be a game-changer for you, especially if you’re keen on optimizing web server functionalities, much like how you’ve learned to enhance service notifications with systemd for Discord.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-22-docker-start-in-network/&#34; &gt;Start a container in a particular docker network&lt;/a&gt;&lt;br&gt;
If you’re jazzed about streamlining your service notifications with Discord, this next piece on effortlessly spinning up Docker containers could be your next tech hack to master!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-03-08-wsl-time-drift/&#34; &gt;Fix WSL time drift&lt;/a&gt;&lt;br&gt;
Keep your development environment in perfect sync; after setting up Discord notifications for service status, ensure your WSL2 VM clock doesn’t fall behind with a simple fix, avoiding potential timestamp and SSL headaches.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Generate PEM file for any Linux user</title>
        <link>https://ishan.page/blog/2021-09-18-pem-linux/</link>
        <pubDate>Sat, 18 Sep 2021 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2021-09-18-pem-linux/</guid>
        <description>&lt;p&gt;Quickly and easily generate a key pair for passwordless connection. Also works perfect as git deploy keys!&lt;/p&gt;
&lt;h2 id=&#34;generate-the-keys&#34;&gt;Generate the keys&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;DO NOT DO THIS AS ROOT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Run the command to generate the keys&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ssh-keygen -P &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; -t rsa -b &lt;span class=&#34;m&#34;&gt;4096&lt;/span&gt; -m pem -f my-key-pair
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-b&lt;/code&gt; flag sets the bits, 4096 is recommended&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-m pem&lt;/code&gt; is needed to generate a file in RSA Private Key format, not in OpenSSH Private Key format&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-f&lt;/code&gt; specifies the output key pair&lt;/li&gt;
&lt;li&gt;replace &lt;code&gt;my-key-pair&lt;/code&gt; with the name of your key pair (preferably &lt;code&gt;deploy_key&lt;/code&gt; or &lt;code&gt;access_key&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will generate two files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;my-key-pair&lt;/code&gt; - this is your PEM file, copy paste the contents&lt;/li&gt;
&lt;li&gt;&lt;code&gt;my-key-pair.pub&lt;/code&gt; - this is the corresponding public key file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: You may want to rename the &lt;code&gt;my-key-pair&lt;/code&gt; to &lt;code&gt;my-key-pair.pem&lt;/code&gt; for convenience.&lt;/p&gt;
&lt;h2 id=&#34;set-the-key-to-allow-login&#34;&gt;Set the key to allow login&lt;/h2&gt;
&lt;p&gt;In order to be able to log in using the generated PEM file, you should add the public key to the authorized_keys list. To do that, run&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Ignore this step if you have other public keys added
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ touch ~/.ssh/authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat my-key-pair.pem &amp;gt;&amp;gt; ~/.ssh/authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-21-linux-use-multiple-git-profiles/&#34; &gt;Using different Github accounts with different private keys on Linux&lt;/a&gt;&lt;br&gt;
After mastering the art of creating a secure 4096-bit RSA key, learning how to juggle multiple GitHub accounts with ease could be your next savvy move in streamlining your development workflow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-11-06-jq-by-example/&#34; &gt;The Ultimate Interactive JQ Guide&lt;/a&gt;&lt;br&gt;
Unlock the power of JSON manipulation with jq, enhancing your SSH key management and deployment strategies by diving into real-world data handling scenarios.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recommended reading not found for slug or filename: &#39;post/power-digits-log-formula-trick&#39;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Build and Deploy Eleventy via SFTP using Github Actions</title>
        <link>https://ishan.page/blog/2021-09-15-eleventy-deploy-github-sftp/</link>
        <pubDate>Wed, 15 Sep 2021 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2021-09-15-eleventy-deploy-github-sftp/</guid>
        <description>&lt;ol&gt;
&lt;li&gt;Navigate to Repository &amp;gt; Settings &amp;gt; Secrets &amp;gt; New Repository Secret&lt;/li&gt;
&lt;li&gt;Set the name as SSH_PRIVATE_KEY&lt;/li&gt;
&lt;li&gt;Paste the contents of the key file&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# .github/workflows/build.yaml&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Build and Deploy PROJECT_NAME&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;branches&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;jobs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;runs-on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;ubuntu-latest&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;strategy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;node-version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;14.&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;x]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/checkout@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/setup-node@v1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;node-version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ matrix.node-version }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Install dependencies &amp;amp; build&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          npm ci
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          npm run build:assets
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          npm run build:site&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;          
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Deploy build&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;wlixcc/SFTP-Deploy-Action@v1.2.1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;domain.user&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;server.host&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ssh_private_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.SSH_PRIVATE_KEY }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;local_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;./dist/*&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;remote_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;site_home_dir&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;-o ConnectTimeout=5&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-21-linux-use-multiple-git-profiles/&#34; &gt;Using different Github accounts with different private keys on Linux&lt;/a&gt;&lt;br&gt;
If you’re streamlining your Eleventy project with GitHub Actions, mastering how to manage multiple GitHub accounts with unique SSH keys on Linux could further enhance your workflow efficiency and security.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/&#34; &gt;Blogging with Jupyter Notebooks in Hugo&lt;/a&gt;&lt;br&gt;
If you’re all about optimizing your development workflow, just like you streamlined Eleventy deployment with GitHub Actions, you’ll appreciate how I leveraged Jupyter notebooks in Hugo to make blogging a breeze.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
After mastering GitHub Actions for your Eleventy project, you might be curious about leveraging APIs to automate other aspects of your digital presence, like fetching leads from Facebook with Python.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Install Postgres into XAMPP on Windows</title>
        <link>https://ishan.page/blog/2019-05-08-windows-xampp-postgres/</link>
        <pubDate>Wed, 08 May 2019 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2019-05-08-windows-xampp-postgres/</guid>
        <description>&lt;h1 id=&#34;setting-up-a-local-postgres-development-environment&#34;&gt;Setting up a local Postgres development environment&lt;/h1&gt;
&lt;h2 id=&#34;1-install-postgres&#34;&gt;1. Install Postgres&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Download the installer from &lt;a class=&#34;link&#34; href=&#34;https://www.enterprisedb.com/downloads/postgres-postgresql-downloads#windows&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;EnterpriseDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Run the installer&lt;/li&gt;
&lt;li&gt;Install Postgres into C:\xampp\pgsql{version_number} folder&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;2-enable-postgres-modules-for-php&#34;&gt;2. Enable PostGres modules for PHP&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Open php.ini file located in C:\xampp\php.&lt;/li&gt;
&lt;li&gt;Uncomment the following lines in php.ini
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;extension=php_pdo_pgsql.dll
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;extension=php_pgsql.dll
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;3-install-adminer&#34;&gt;3. Install Adminer&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Download &lt;a class=&#34;link&#34; href=&#34;https://www.adminer.org/#download&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Adminer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Place the PHP file into HTDOCS&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;4-wrapping-up&#34;&gt;4. Wrapping up&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Restart Apache&lt;/li&gt;
&lt;li&gt;Adminer is now accessible &lt;a class=&#34;link&#34; href=&#34;http://localhost/adminer.php&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2015-11-03-apache-php5/&#34; &gt;How to install and optimize Apache with mpm_event, php5-fpm and MariaDB&lt;/a&gt;&lt;br&gt;
Unlock the full potential of your limited-resource server by mastering these LAMP stack optimization techniques, ensuring your web hosting is as efficient as possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-15-hugo-ipython-jupyter/&#34; &gt;Blogging with Jupyter Notebooks in Hugo&lt;/a&gt;&lt;br&gt;
After mastering the integration of Postgres with XAMPP to enhance your local development setup, you might be intrigued by how I transformed my blogging workflow by embracing Jupyter notebooks, a move that could inspire you to streamline your own development and publishing processes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
After mastering local development setup with Postgres and XAMPP, you might be eager to explore how to leverage APIs to enhance your projects, and this guide on fetching leads from Facebook using Python is a perfect next step!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>3 ways to render inline lists in PHP</title>
        <link>https://ishan.page/blog/2019-04-15-php-inline-lists/</link>
        <pubDate>Mon, 15 Apr 2019 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2019-04-15-php-inline-lists/</guid>
        <description>&lt;p&gt;Given a list of items and a separator, render it in a single line, with separators between.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$items&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;apples&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;oranges&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;bananas&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$separator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; / &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;method-1-basic-foreach&#34;&gt;Method 1: Basic &lt;code&gt;foreach&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This approach is the one that comes to mind first, but it is incorrect because it will emit an
additional separator after the last element.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$items&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$separator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apples / oranges / bananas /
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;method-2-using-implode&#34;&gt;Method 2: Using &lt;code&gt;implode()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Cleaner and shorter, this usage is appropriate for most applications:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;implode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$separator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apples / oranges / bananas
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;While the &lt;code&gt;implode()&lt;/code&gt; method is great for most purposes, it does break down when there is heavy templating
involved.&lt;/p&gt;
&lt;h2 id=&#34;method-3-using-foreach-and&#34;&gt;Method 3: Using &lt;code&gt;foreach&lt;/code&gt; and&lt;/h2&gt;
&lt;p&gt;When heavier templating functionality is required, it&amp;rsquo;s best to use&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$items&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!==&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;array_key_last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$separator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The third method has the same output as the second one, but gives you more flexibility in how you might organize
your templates.&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2015-11-03-apache-php5/&#34; &gt;How to install and optimize Apache with mpm_event, php5-fpm and MariaDB&lt;/a&gt;&lt;br&gt;
Unlock the full potential of your VPS with these expert tips on fine-tuning your LAMP stack, ensuring your web projects run smoothly even on servers with limited resources.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Exploring how I tackled HTML generation with jq might spark new ideas for your own projects, especially if you enjoy creative solutions in coding.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
Unlock the power of data retrieval from social media with a Python script, a perfect next step after mastering PHP list rendering techniques.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>How to install and optimize Apache with mpm_event, php5-fpm and MariaDB</title>
        <link>https://ishan.page/blog/2015-11-03-apache-php5/</link>
        <pubDate>Tue, 03 Nov 2015 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2015-11-03-apache-php5/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A note to the reader&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This post is a legacy post. The legacy posts that are available on this website were written many years ago. These posts are made available here &lt;strong&gt;for archival purposes only&lt;/strong&gt;.&lt;br&gt;
They reflect the age I was, and the level of knowledge that I had when I wrote them, and they &lt;strong&gt;may contain outdated information&lt;/strong&gt;, so please keep that in mind as you proceed to read this article.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Original Title&lt;/strong&gt;: How to install a highly optimized LAMP stack with mpm_event and MariaDB&lt;/p&gt;
&lt;p&gt;Apache is today more important as a web server than ever before. Most PHP scripts assume (or even require) apache to be installed in order to run. However, for most people running a VPS with less than a GB of RAM, having to run apache is a deal breaker. The same applies for the stock MySQL configuration. This tutorial will help you to install Apache with the event MPM + PHP [fastcgi] + MariaDB 5.5&lt;/p&gt;
&lt;h2 id=&#34;step-1---install-prerequisites&#34;&gt;Step 1 - Install Prerequisites&lt;/h2&gt;
&lt;p&gt;This tutorial requires root. If you&amp;rsquo;re not already root, run this command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo su
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;and gain root priviledges. Alternatively, you may prefix the commands with &lt;code&gt;sudo&lt;/code&gt; also.
We will use the aptitude package manager as a replacement for apt-get. Since it is not available by default, go ahead and install it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apt-get install -y aptitude
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-2---install-apache&#34;&gt;Step 2 - Install Apache&lt;/h2&gt;
&lt;p&gt;Apache is sometimes included by default by ubuntu, however aptitude will take care of removing the preform mpm when we install the apache fastcgi module, and the event mpm&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aptitude install -y libapache2-mod-fastcgi apache2-mpm-event
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then, we disable the build in apache php modules as they consume too much precious memory&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2dismod php4 # PHP v4 is outdated. It should be criminal to even have it on a system
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2dismod php5 # mod_php is not usable with worker mpm, therefore we disable it
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2dismod fcgid # fcgid is not required. We will set up fastcgi later.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then, we will enable the mod_fastcgi, mod_ssl, mod_actions and mod_rewrite&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2enmod fastcgi
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2enmod ssl
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2enmod actions
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a2enmod rewrite
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-3---install-php&#34;&gt;Step 3 - Install PHP&lt;/h2&gt;
&lt;p&gt;We will be running PHP as a FastCGI process. We will configure FastCGI to run as a separate server and have a 120 second timeout.&lt;/p&gt;
&lt;p&gt;First, we configure the apache2 fastcgi module.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nano /etc/apache2/mods-available/fastcgi.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;IfModule mod_fastcgi.c&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FastCgiIpcDir /var/lib/apache2/fastcgi
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Set FPM to run externally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FastCGIExternalServer /srv/www/fcgi-bin.d/php5-fpm -pass-header Authorization -idle-timeout 120 -socket /var/run/php5-fpm-www-data.sock
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Alias /php5-fcgi /srv/www/fcgi-bin.d
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AddType application/x-httpd-php5 .php
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# FPM will handle all PHP files
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;FilesMatch &amp;#34;\.php$&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SetHandler php-fpm
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/FilesMatch&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Action php-fpm /php5-fcgi/php5-fpm
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Prevent external access to FPM directory
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Location &amp;#34;/php5-fcgi/php5-fpm&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Order deny,allow
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Deny from All
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Allow from env=REDIRECT_STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/Location&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/IfModule&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Finish off by creating the FPM directory&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir -p /srv/www/fcgi-bin.d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then, we install the php packages
Base PHP packages. Essential to run PHP&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aptitude install -y php5-fpm php5-common php-apc php5-mysqlnd php5-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Secondary, but useful PHP modules/packages. Feel free to omit&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aptitude install -y php5-memcache php5-curl php5-mcrypt php5-xsl php5-gd php5-imagick php5-snmp php5-xmlrpc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And, we&amp;rsquo;re done installing PHP&lt;/p&gt;
&lt;h2 id=&#34;step-4---install-mariadb&#34;&gt;Step 4 - Install MariaDB&lt;/h2&gt;
&lt;p&gt;We will be using MariaDB as our database server. It is an enhanced, drop-in replacement for MySQL that is developed by the original team and is more performant&lt;/p&gt;
&lt;p&gt;Install MariaDB&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aptitude -y install mariadb-server mariadb-client
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Secure MariaDB&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mysql_secure_installation
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And we&amp;rsquo;re done!&lt;/p&gt;
&lt;h2 id=&#34;step-5---pre-optimization&#34;&gt;Step 5 - Pre-Optimization&lt;/h2&gt;
&lt;p&gt;Before we optimize, we need to restart apache2 and php.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;service php5-fpm restart
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apache2ctl graceful
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-6---optimize-apache&#34;&gt;Step 6 - Optimize Apache&lt;/h2&gt;
&lt;p&gt;The only optimization apache really needs is the config optimization.
Edit the config file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nano /etc/apache2/apache2.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;92
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-v&#34; data-lang=&#34;v&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LockFile&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;APACHE_LOCK_DIR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;accept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;PidFile&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;APACHE_PID_FILE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Timeout&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;300&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;KeepAlive&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;On&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;MaxKeepAliveRequests&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;KeepAliveTimeout&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IfModule&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mpm_worker_module&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;StartServers&lt;/span&gt;          &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MinSpareThreads&lt;/span&gt;      &lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MaxSpareThreads&lt;/span&gt;      &lt;span class=&#34;mi&#34;&gt;75&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;ThreadLimit&lt;/span&gt;          &lt;span class=&#34;mi&#34;&gt;64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;ThreadsPerChild&lt;/span&gt;      &lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MaxClients&lt;/span&gt;          &lt;span class=&#34;mi&#34;&gt;150&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MaxRequestsPerChild&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IfModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IfModule&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mpm_event_module&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;StartServers&lt;/span&gt;          &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MinSpareThreads&lt;/span&gt;       &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MaxSpareThreads&lt;/span&gt;       &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;ThreadLimit&lt;/span&gt;           &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;ThreadsPerChild&lt;/span&gt;       &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MaxClients&lt;/span&gt;            &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;MaxRequestsPerChild&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;5000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IfModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;These&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;need&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;be&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;etc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;apache2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;envvars&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;User&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;APACHE_RUN_USER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Group&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;APACHE_RUN_GROUP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;AccessFileName&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;htaccess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;The&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;following&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;lines&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;prevent&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;htaccess&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;htpasswd&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;files&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;being&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;viewed&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Web&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;clients&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Files&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^\.ht&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;Order&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;allow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;deny&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;Deny&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;Satisfy&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Files&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Directory&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;Options&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Indexes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FollowSymLinks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;AllowOverride&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;All&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nc&#34;&gt;Order&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;allow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;deny&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;allow&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;DefaultType&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;HostnameLookups&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Off&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;ErrorLog&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;APACHE_LOG_DIR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;log&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LogLevel&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;warn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;module&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;configuration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;enabled&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;load&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;enabled&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;list&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ports&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;listen&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;on&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;which&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;based&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vhosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;The&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;following&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;directives&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;define&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;some&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;format&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;nicknames&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;use&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;CustomLog&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;directive&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;see&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;below&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;If&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;you&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;are&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;behind&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;reverse&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;proxy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;you&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;might&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;want&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;change&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;h&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;into&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Forwarded&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;For&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LogFormat&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%v:%p %h %l %u %t &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%r&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %&amp;gt;s %O &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%{Referer}i&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%{User-Agent}i&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vhost_combined&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LogFormat&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%h %l %u %t &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%r&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %&amp;gt;s %O &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%{Referer}i&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%{User-Agent}i&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;combined&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LogFormat&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%h %l %u %t &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%r&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %&amp;gt;s %O&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;common&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LogFormat&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%{Referer}i -&amp;gt; %U&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;referer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;LogFormat&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%{User-agent}i&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;agent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;generic&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;snippets&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;statements&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;conf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;configurations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nc&#34;&gt;Include&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;sites&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;enabled&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-7---optimize-fpm&#34;&gt;Step 7 - Optimize FPM&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: Most of these steps are done with automated linux tools like &lt;code&gt;sed&lt;/code&gt; which make it easy to edit the configuration files. If you want to know what&amp;rsquo;s going on
behind the scenes, refer to the comments above each command block.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Before we optimize FPM, we need to stop the service&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;service php5-fpm stop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The FPM configuration file is lengthy and complex. To quickly do the configuration automatically, run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;php_fpm_conf=&amp;#34;/etc/php5/fpm/pool.d/www.conf&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Configure these values to your liking. Optimized for 512MB RAM VPS
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FPM_MAX_CHILDREN=5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FPM_START_SERVERS=1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FPM_MIN_SPARE_SERVERS=1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FPM_MAX_SPARE_SERVERS=2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FPM_MAX_REQUESTS=5000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;pm.max_children&lt;/code&gt; is the configuration value that controls the maximum number of server processes that will be
started by FastCGI. 5 is usually enough, but it might be a good idea to set it to 10 or 15 for a high traffic site
on a high-end vps&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^pm.max_children.*/pm.max_children = &amp;#39;${FPM_MAX_CHILDREN}&amp;#39;/&amp;#39; $php_fpm_conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;pm.start_servers&lt;/code&gt; is the number of servers to be initially started by FastCGI. 1 is nearly always enough. Try 2 or 3 for higher traffic sites. Make sure that is it less that &lt;code&gt;pm.max_children&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^pm.start_servers.*/pm.start_servers = &amp;#39;${FPM_START_SERVERS}&amp;#39;/&amp;#39; $php_fpm_conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;pm.min_spare_servers&lt;/code&gt; is the minimum number of server processes FastCGI will have ready to handle additional load. Each server process is respawned when it hits &lt;code&gt;pm.max_requests&lt;/code&gt;. It is here that this value becomes useful. It ensures that the site will not go offline for even a small amount of time, and will remain performant even under load. 1 is enough for small sites (&amp;lt; 5000 views / minute). For larger sites, try 5 or 6.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^pm.min_spare_servers.*/pm.min_spare_servers = &amp;#39;${FPM_MIN_SPARE_SERVERS}&amp;#39;/&amp;#39; $php_fpm_conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;pm.max_spare_servers&lt;/code&gt; exists for only one reason: to prevent FastCGI from consuming too many resources in the event of high load. This is the
number of maximum server processes that will be kept ready by FastCGI. Make sure it is at least half of &lt;code&gt;pm.max_children&lt;/code&gt; and greater than
&lt;code&gt;pm.min_spare_server&lt;/code&gt;s. 2 is OK for a small site. Try 9 or 10 for a large site&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^pm.max_spare_servers.*/pm.max_spare_servers = &amp;#39;${FPM_MAX_SPARE_SERVERS}&amp;#39;/&amp;#39; $php_fpm_conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;pm.max_requests&lt;/code&gt; controls the maximum number of hits a FastCGI process is allowed to serve before it is killed and respawned. This value
is there in place to deal with the fact that over time, these processes leak memory. Periodically killing and respawning them allows
us to keep the site snappy. 5000 is a pretty good value to begin with, give or take a couple hundreds. If &lt;code&gt;pm.min_spare_server&lt;/code&gt;s is &amp;lt; 5, and
this value is &amp;lt; 5000, the site will become more sluggish. Never set it to a 3 digit or less number. Always ensure that it is &amp;gt;= 5000&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/\;pm.max_requests.*/pm.max_requests = &amp;#39;${FPM_MAX_REQUESTS}&amp;#39;/&amp;#39; $php_fpm_conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Change to socket connection for better performance&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^listen =.*/listen = \/var\/run\/php5-fpm-www-data.sock/&amp;#39; $php_fpm_co
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now, configure the php.ini file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;php_ini_dir=&amp;#34;/etc/php5/fpm/php.ini&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Configure these values to your liking. Optimized for 512MB RAM VPS
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PHP_MEMORY_LIMIT=192M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PHP_MAX_EXECUTION_TIME=120
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PHP_MAX_INPUT_TIME=300
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PHP_POST_MAX_SIZE=50M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PHP_UPLOAD_MAX_FILESIZE=50
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;max_execution_time&lt;/code&gt; is the maximum amount of time (in seconds) that a script is allowed to execute for, before it is killed. 120 is a big enough number to do most heavy calculations, but this number may be increased if many computations are required to be performed or heavy downloading needs to be done.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^max_execution_time.*/max_execution_time = &amp;#39;${PHP_MAX_EXECUTION_TIME}&amp;#39;/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;memory_limit&lt;/code&gt; is the maximum amount of memory (in MB) that a PHP script is allowed to take up. 192 is more than
enough for most jobs, but you may consider raising it if you want to do heavy computations.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^memory_limit.*/memory_limit = &amp;#39;${PHP_MEMORY_LIMIT}&amp;#39;/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is the maximum amount of time (in seconds) for which a client can upload data to the server through a keep-alive connection. 300 seconds (or 5 minutes) is usually enough. You may want to set it to something like 6300 (2 hours) if you plan on uploading huge files.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^max_input_time.*/max_input_time = &amp;#39;${PHP_MAX_INPUT_TIME}&amp;#39;/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;post_max_size&lt;/code&gt; is the maximum size (in MB) of the data that can be sent to the server through a POST request. 50 MB is usually more than enough for most needs, but feel free to change to will.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^post_max_size.*/post_max_size = &amp;#39;${PHP_POST_MAX_SIZE}&amp;#39;/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;upload_max_filesize&lt;/code&gt; is the maximum size of an individual file (in MB) that can be uploaded. Change at will.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^upload_max_filesize.*/upload_max_filesize = &amp;#39;${PHP_UPLOAD_MAX_FILESIZE}&amp;#39;/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Don&amp;rsquo;t expose PHP. More of a security fix than memory optimization&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^expose_php.*/expose_php = Off/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Disable potentially dangerous PHP functions that may allow attackers to execute arbitary code on your machine.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^disable_functions.*/disable_functions = exec,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,dl,popen,show_source/&amp;#39; $php_ini_dir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now we restart all the services&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;service php5-fpm start
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;service php5-fpm restart
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apache2ctl graceful
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-8---optimize-mariadb&#34;&gt;Step 8 - Optimize MariaDB&lt;/h2&gt;
&lt;p&gt;MariaDB configuration is quite easy to optimize. Just dropping InnoDB can cause a huge performance gain.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nano /etc/mysql/my.cnf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[mysqld]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;default-storage-engine = myisam
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;key_buffer = 1M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;query_cache_size = 1M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;query_cache_limit = 128k
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;max_connections=25
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;thread_cache=1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;skip-innodb
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;query_cache_min_res_unit=0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tmp_table_size = 1M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;max_heap_table_size = 1M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table_cache=256
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;concurrent_insert=2 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;max_allowed_packet = 1M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sort_buffer_size = 64K
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;read_buffer_size = 256K
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;read_rnd_buffer_size = 256K
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;net_buffer_length = 2K
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;thread_stack = 64K
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;END
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now we restart the service&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;service mysql restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-9---reboot&#34;&gt;Step 9 - Reboot&lt;/h2&gt;
&lt;p&gt;Reboot the server to get better performance&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;shutdown -r now
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-11---set-up-a-non-root-sudo-enabled-user&#34;&gt;Step 11 - Set up a non-root sudo-enabled user&lt;/h2&gt;
&lt;p&gt;We will use this user&amp;rsquo;s home directory to contain our vhosts.
Add the User&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;adduser demo # Replace demo with your name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Like `adduser ishan`
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Grant him priviledges&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gpasswd -a demo sudo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;step-12---add-a-virtualhost&#34;&gt;Step 12 - Add a virtualhost&lt;/h2&gt;
&lt;p&gt;Replace &amp;ldquo;example.com&amp;rdquo; with your domain
Replace &amp;ldquo;demo&amp;rdquo; with your user
Create an FPM user&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DOMAIN_OWNER=demo
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp /etc/php5/fpm/pool.d/{www.conf,$DOMAIN_OWNER.conf}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Quickly edit the FPM file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Create a new FPM pool with same name as user
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^\[www\]$/\[&amp;#39;${DOMAIN_OWNER}&amp;#39;\]/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# set it to listen on a unix socket
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^listen =.*/listen = \/var\/run\/php5-fpm-&amp;#39;${DOMAIN_OWNER}&amp;#39;.sock/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# set permissions
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^user = www-data$/user = &amp;#39;${DOMAIN_OWNER}&amp;#39;/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^group = www-data$/group = &amp;#39;${DOMAIN_OWNER}&amp;#39;/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^;listen.mode =.*/listen.mode = 0660/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^;listen.owner =.*/listen.owner = www-data/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -i &amp;#39;s/^;listen.group =.*/listen.group = www-data/&amp;#39; /etc/php5/fpm/pool.d/$DOMAIN_OWNER.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Restart FPM&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;service php5-fpm restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Create a public_html for your domain&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir -p /home/demo/example_com/public_html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Create the log files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;touch /home/demo/test_digitalocean_tk/logs/{access.log,error.log}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Set permissions&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chown demo:demo /home/demo/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chown -R demo:demo /home/demo/example_com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Allow execute permissions to group and other so that the webserver can serve files
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod 711 /home/demo/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod 711 /home/demo/example_com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Create the VirtualHost file&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nano /etc/apache2/sites-available/example_com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;VirtualHost *:80&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ServerName example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ServerAlias www.example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ServerAdmin admin@example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    DocumentRoot /home/demo/example_com/public_html/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ErrorLog /home/demo/example_com/logs/error.log
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    CustomLog /home/demo/example_com/logs/access.log combined
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    FastCGIExternalServer /home/demo/example_com/php5-fpm -pass-header Authorization -idle-timeout 120 -socket /var/run/php5-fpm-demo.sock
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Alias /php5-fcgi /home/demo/example_com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/VirtualHost&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Enable the virtualhost&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ln -s /etc/apache2/sites-available/example_com /etc/apache2/sites-available/example_com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Test the virtualhost&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nano /home/demo/example_com/public_html/info.php
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;?php
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;phpinfo();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;?&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;navigate to your domain in the browser and see that it&amp;rsquo;s working correctly.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Now that you know how to install and optimize a LAMP stack, get cracking and create a great site that will be big enough to crash this setup!&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-05-08-windows-xampp-postgres/&#34; &gt;Install Postgres into XAMPP on Windows&lt;/a&gt;&lt;br&gt;
After mastering LAMP stack optimizations for Linux, you might be intrigued by the versatility of integrating Postgres with XAMPP on Windows, expanding your development environment capabilities.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-04-15-php-inline-lists/&#34; &gt;3 ways to render inline lists in PHP&lt;/a&gt;&lt;br&gt;
After mastering the art of optimizing your LAMP stack for peak performance, you’ll appreciate the finesse of using PHP to seamlessly render inline lists, a skill that complements your server optimization efforts by enhancing your web applications’ efficiency and user experience.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-11-28-bashrc-oopsie-deleted/&#34; &gt;Accidentally deleted your .bashrc?&lt;/a&gt;&lt;br&gt;
After mastering the art of optimizing your LAMP stack, learning how to recover and customize your bash environment can be your next step to becoming a Linux server wizard.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Scraping the MPB website - A Postmortem</title>
        <link>https://ishan.page/blog/2014-10-09-mpb-scraper-postmortem/</link>
        <pubDate>Thu, 09 Oct 2014 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2014-10-09-mpb-scraper-postmortem/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A note to the reader&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This post is a legacy post. The legacy posts that are available on this website were written many years ago. These posts are made available here &lt;strong&gt;for archival purposes only&lt;/strong&gt;.&lt;br&gt;
They reflect the age I was, and the level of knowledge that I had when I wrote them, and they &lt;strong&gt;may contain outdated information&lt;/strong&gt;, so please keep that in mind as you proceed to read this article.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Last week, I scraped the &lt;a class=&#34;link&#34; href=&#34;http://mpbfhsschool.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;School Website&lt;/a&gt; clean looking for report cards. I wanted the data to do some statistics (the website is very spartan) and, much to my pleasure, I was successfully able to get all the data I need.&lt;/p&gt;
&lt;h1 id=&#34;the-problem&#34;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;I need the report card data in &lt;strong&gt;JSON&lt;/strong&gt; format. The format given is, quite unsurprisingly, Bad HTML&lt;/p&gt;
&lt;h2 id=&#34;problem-1-bad-html&#34;&gt;Problem 1: Bad HTML&lt;/h2&gt;
&lt;p&gt;The Website is built with ASP.NET. What better can I expect?
&lt;strong&gt;Tables in tables&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;table&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;100%&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;border&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;cellspacing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;cellpadding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;border-bottom: 1px #000000 solid&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;border-right: 1px #000000 solid&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;ni&#34;&gt;&amp;amp;nbsp;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000000; padding: 3px 3px 3px 5px;border-right: 1px #000000 solid&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Subject&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s an example of the stuff I had to deal with&lt;/p&gt;
&lt;h2 id=&#34;problem-2-inconsistent-id-numbers&#34;&gt;Problem 2: Inconsistent ID Numbers&lt;/h2&gt;
&lt;p&gt;Come on. Who would expect people from Class 11 and 12 to have joined the school in 2014?&lt;/p&gt;
&lt;h1 id=&#34;the-solution&#34;&gt;The Solution&lt;/h1&gt;
&lt;h2 id=&#34;solution-1-xpath&#34;&gt;Solution 1: Xpath&lt;/h2&gt;
&lt;p&gt;XPath is what saved me. True, it took some analysis, but I got a working thing ready&lt;/p&gt;
&lt;h2 id=&#34;solution-2-python--lxml&#34;&gt;Solution 2: Python + lxml&lt;/h2&gt;
&lt;p&gt;Python was used to write the bruteforcing script. It&amp;rsquo;s what helped me to make it easier to work with the tedious job&lt;/p&gt;
&lt;p&gt;Lxml was used to parse the Xpath and extract the data&lt;/p&gt;
&lt;p&gt;Finally some helper scripts made the data into yearly chunks, classes, segregated and organized it into nice self-contained JSON files&lt;/p&gt;
&lt;h2 id=&#34;solution-3-koding&#34;&gt;Solution 3: Koding&lt;/h2&gt;
&lt;p&gt;My internet is too slow to allow the script to be practical. A VPS from &lt;a class=&#34;link&#34; href=&#34;http://koding.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Koding&lt;/a&gt; helped me to get the job done in minutes instead of weeks.&lt;/p&gt;
&lt;p&gt;The entire extraction took 15 Mins on the VPS. There were some &amp;gt;2500 Records,
My connection can do 25.1 records in 15 mins&lt;/p&gt;
&lt;h1 id=&#34;what-went-right&#34;&gt;What went Right&lt;/h1&gt;
&lt;p&gt;The extraction and processing&lt;/p&gt;
&lt;h1 id=&#34;what-went-wrong&#34;&gt;What went Wrong&lt;/h1&gt;
&lt;p&gt;A lot of things&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Firstly, I could have used threading. It would have made everything much much faster&lt;/li&gt;
&lt;li&gt;Secondly, I should have used &lt;a class=&#34;link&#34; href=&#34;http://scrapy.org&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Scrapy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Thirdly, I should have done my homework about the subjects and classes&lt;/li&gt;
&lt;li&gt;Fourthly, I did a lot of useless year-crawling like 2000 and 1998&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;downloads&#34;&gt;Downloads&lt;/h1&gt;
&lt;p&gt;Ok. Here you go: &lt;strong&gt;data download link is now removed&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Explore how I tackled a unique challenge using jq for HTML generation, mirroring the inventive spirit you saw in my data scraping adventure, and highlighting the value of adaptability in tech.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
After tackling the complexities of web scraping, you might be curious about harnessing APIs for data retrieval, offering a smoother path to gather specific online information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2019-05-08-windows-xampp-postgres/&#34; &gt;Install Postgres into XAMPP on Windows&lt;/a&gt;&lt;br&gt;
After wrestling with data extraction, you might appreciate the simplicity of setting up a robust local development environment with Postgres and XAMPP to streamline your future projects.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Gamedev Ideas</title>
        <link>https://ishan.page/blog/2014-09-07-gamedev-ideas/</link>
        <pubDate>Sun, 07 Sep 2014 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2014-09-07-gamedev-ideas/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A note to the reader&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This post is a legacy post. The legacy posts that are available on this website were written many years ago. These posts are made available here &lt;strong&gt;for archival purposes only&lt;/strong&gt;.&lt;br&gt;
They reflect the age I was, and the level of knowledge that I had when I wrote them, and they &lt;strong&gt;may contain outdated information&lt;/strong&gt;, so please keep that in mind as you proceed to read this article.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Hello there.
I&amp;rsquo;ve recently spent quite some time thinking up innovative ideas for my games,
Here is the list I came up with:&lt;/p&gt;
&lt;h1 id=&#34;idea-list&#34;&gt;Idea List&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Web Dev Simulator&lt;/li&gt;
&lt;li&gt;Hole Skating&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;web-dev-simulator&#34;&gt;Web Dev Simulator&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;You are a website developer.
You have a budget
You need money
OK. Enough small talk; &lt;strong&gt;GET WORKING!!!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I intend this to be sort of a joke, possibly a stab at the world of SEO and &lt;strong&gt;&amp;ldquo;Professional&amp;rdquo;&lt;/strong&gt; website development. You might have to purchase SEO packs, and choose a web host from a randomly generated list of names. They might range from &lt;strong&gt;Free-and-Scammy&lt;/strong&gt; to &lt;strong&gt;Expensive-and-Professional&lt;/strong&gt;. Your host might have downtime, the search engines might lower your ranking, it&amp;rsquo;s all possible in this game. Also, the only reason I&amp;rsquo;m making a simulator is because of the simulator craze started by PewDiePie. &lt;em&gt;Surgeon Simulator, I&amp;rsquo;m looking at you.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;hole-skating&#34;&gt;Hole Skating&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;You are lying in bed, and are suddenly woken up from your beauty-sleep by the
sound on metal-on-ice. You rush out of bed and look through the window, and what
do you see?&lt;/p&gt;
&lt;p&gt;You see people who are skating on the ice. That&amp;rsquo;s irritating, you think,
expecially as they have not taken your permission and it&amp;rsquo;s your backyard.&lt;/p&gt;
&lt;p&gt;Wait a minute. How did your backyard freeze?
&lt;strong&gt;THOSE IDIOTS MUST HAVE POURED WATER ON IT!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You put on your sweater, your muffler and skates. You attach a salt shaker to
the skates. Now, let&amp;rsquo;s teach them a lesson&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pardon me for making you read all that backstory, I got carried away :P&lt;/p&gt;
&lt;p&gt;In this game, your objective is to create holes in the ice, and make other people fall through. Beware, the holes will eventually freeze over again, and the people will keep getting smarter. Don&amp;rsquo;t fall into the hole you thawed for others, though.&lt;/p&gt;
&lt;h1 id=&#34;the-end&#34;&gt;The End&lt;/h1&gt;
&lt;p&gt;What do you think about these ideas? Want to contribute resources for their development? Want to raze them to the ground? Let me know what you think&lt;/p&gt;
&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-hello-world/&#34; &gt;Hello World&lt;/a&gt;&lt;br&gt;
If you enjoyed exploring early game development ideas, you’ll likely appreciate my journey to rejuvenate my online presence, tackling challenges with a blend of creativity and tech savvy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2014-07-20-benchmark-public-cdn/&#34; &gt;Benchmark public javascipt CDNs on a VPS&lt;/a&gt;&lt;br&gt;
Explore how my early fascination with web development evolved into creating a practical tool to enhance your website’s performance by choosing the fastest CDN for your needs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-07-09-programming-with-the-grain/&#34; &gt;Programming &amp;quot;with the grain&amp;quot;&lt;/a&gt;&lt;br&gt;
After exploring the quirky world of game development, you might appreciate the deeper dive into how understanding the core principles of programming can elevate your projects, just like the nuances of game design did for “Web Dev Simulator” and “Hole Skating.”&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Benchmark public javascipt CDNs on a VPS</title>
        <link>https://ishan.page/blog/2014-07-20-benchmark-public-cdn/</link>
        <pubDate>Sun, 20 Jul 2014 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/blog/2014-07-20-benchmark-public-cdn/</guid>
        <description>&lt;blockquote&gt;
&lt;p&gt;This is a legacy script from when I was 13 years old. Please don&amp;rsquo;t give me a hard time&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; speedTest &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;c1&#34;&gt;# ripped off from http://freevps.us/downloads/bench.sh &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nb&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;the_speed&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt; wget -O /dev/null &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;/\/dev\/null/ {speed = $3 $4} END {gsub(/\(|\)/,&amp;#34;&amp;#34;,speed); print speed}&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$the_speed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;jsTest.sh by IshanDS www.ishands.cf&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# CDNJs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;cdnjs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;speedTest &lt;span class=&#34;s2&#34;&gt;&amp;#34;cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Speed from CDNJs:             &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$cdnjs&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Google CDN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;google&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;speedTest &lt;span class=&#34;s2&#34;&gt;&amp;#34;ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Speed from Google CDN:        &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$google&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# jsDelivr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;jsdelivr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;speedTest &lt;span class=&#34;s2&#34;&gt;&amp;#34;cdn.jsdelivr.net/jquery/2.1.1/jquery.min.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Speed from jsDelivr:          &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$jsdelivr&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# MaxCDN OSS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;maxcdn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;speedTest &lt;span class=&#34;s2&#34;&gt;&amp;#34;oss.maxcdn.com/jquery/2.1.1/jquery.min.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Speed from MaxCDN:            &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$maxcdn&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Jquery CDN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;jquery&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;speedTest &lt;span class=&#34;s2&#34;&gt;&amp;#34;code.jquery.com/jquery-2.1.1.min.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Speed from Jquery CDN:        &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$jquery&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Microsoft CDN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;microsoft&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;speedTest &lt;span class=&#34;s2&#34;&gt;&amp;#34;ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.1.min.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Speed from Microsoft CDN:     &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$microsoft&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Thank you for using jsTest.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id=&#34;read-next&#34;&gt;Read Next&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m running &lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/read-this-next-embeddings-llm-rag/&#34; &gt;an experiment&lt;/a&gt; for better content recommendations. These are the 3 posts that are most likely to be interesting for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-12-07-jq-hammer-nails/&#34; &gt;To A Man With &lt;code&gt;jq&lt;/code&gt;, Everything Looks Like JSON&lt;/a&gt;&lt;br&gt;
Exploring unconventional tools can unlock new potentials in web development, just as I found creative ways to use jq for HTML generation, mirroring how you might innovate with scripts like &lt;code&gt;jsTest.sh&lt;/code&gt; for CDN benchmarking.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-20-facebook-graph-leads-between/&#34; &gt;Get leads collected by a particular lead ad form between two timestamps using Facebook Graph API&lt;/a&gt;&lt;br&gt;
After mastering CDN performance with bash, you’ll find harnessing Facebook’s API with Python an exciting next step to broaden your coding toolkit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://ishan.page/blog/2023-06-22-docker-start-in-network/&#34; &gt;Start a container in a particular docker network&lt;/a&gt;&lt;br&gt;
If you’re keen on optimizing web development workflows, this script’s approach to effortlessly setting up Docker containers could be the next efficiency hack you’re looking for.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Newsletter</title>
        <link>https://ishan.page/newsletter/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/newsletter/</guid>
        <description>&lt;p&gt;I&amp;rsquo;ve been trying to be more regular about &lt;a class=&#34;link&#34; href=&#34;https://austinkleon.com/show-your-work/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;showing my work&lt;/a&gt;. This newsletter is part of that endeavour. I know I have an aversion to sharing incomplete work because I worry about what people will think. This is where I try to change that.&lt;/p&gt;
&lt;p&gt;What will you get by subscribing?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Once a week max. No spam, I promise!&lt;/li&gt;
&lt;li&gt;Catch up on any new blog content since the last issue.&lt;/li&gt;
&lt;li&gt;Expect sneak peeks, early access, or even some exclusive content.&lt;/li&gt;
&lt;li&gt;Getting mail is one of the highlights of my day! Share your thoughts, questions, and insights, I will reply back.&lt;/li&gt;
&lt;li&gt;Occasionally, there might be surprises.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;subscribe-now&#34;&gt;Subscribe Now&lt;/h2&gt;
&lt;form
  action=&#34;https://buttondown.email/api/emails/embed-subscribe/ishan.page&#34;
  method=&#34;post&#34;
  target=&#34;popupwindow&#34;
  onsubmit=&#34;window.open(&#39;https://buttondown.email/ishan.page&#39;, &#39;popupwindow&#39;)&#34;
  class=&#34;embeddable-buttondown-form&#34;
&gt;
  &lt;input type=&#34;email&#34; name=&#34;email&#34; class=&#34;bd-text&#34; id=&#34;bd-email&#34; placeholder=&#34;Your Email&#34;/&gt; 
  &lt;input type=&#34;text&#34; name=&#34;metadata__name&#34; class=&#34;bd-text&#34; id=&#34;name&#34; placeholder=&#34;Your Name (Optional)&#34;/&gt; 
  &lt;input type=&#34;submit&#34; value=&#34;Subscribe&#34; /&gt;
&lt;/form&gt;
</description>
        </item>
        <item>
        <title>Search</title>
        <link>https://ishan.page/search/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://ishan.page/search/</guid>
        <description></description>
        </item>
        
    </channel>
</rss>
