<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Shrey Banga's blog</title>
    <link href="https://shreyb.dev/blog/atom.xml" rel="self" />
    <link href="https://shreyb.dev/blog/" />
    <updated>2024-02-02T00:00:00.000Z</updated>
    <id>https://shreyb.dev/blog/atom.xml</id>
    <author>
        <name>Shrey Banga</name>
    </author>
<entry>
      <title>Learning Rust in 3 attempts</title>
      <link href="https://shreyb.dev/blog/2024/02/02/learning-rust.html" />
      <updated>2024-02-02T00:00:00.000Z</updated>
      <id>https://shreyb.dev/blog/2024/02/02/learning-rust.html</id>
      <author>
        <name>Shrey Banga</name>
      </author>
      <content type="html">&lt;h1&gt;Learning Rust in 3 attempts&lt;/h1&gt;
&lt;p&gt;One of my earliest programming languages was C++, which for all its warts, was a giant leap from my first language, BASIC. I especially enjoyed understanding precisely what&amp;#x27;s happening at the CPU and memory level&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; to my program when it runs.&lt;/p&gt;
&lt;p&gt;Once I got a Real Job, I moved on to higher level languages and spent the last decade mostly writing JavaScript and Python. These are both exceedingly powerful languages that have been a joy to build stuff with, but they do sometimes make you miss the low level control of a systems language&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. But C++ had moved on quite a bit since I last wrote it and it didn&amp;#x27;t really entice me as a pleasant language to use on the side.&lt;/p&gt;
&lt;p&gt;So Rust had my attention when I first heard of it and made a few attempts at learning it. I&amp;#x27;ve finally reached a point where I feel comfortable and productive in it, so I thought I&amp;#x27;d log my progress in case it helps someone get there faster.&lt;/p&gt;
&lt;h2&gt;Attempt 1: RTFM&lt;/h2&gt;
&lt;p&gt;For all of the languages I&amp;#x27;ve learned in recent memory (TypeScript, Go, Python), my process was the same – read the official manual, start using it and read the documentation as needed. So back in 2019, I did the same with Rust. I read &lt;a href=&quot;https://doc.rust-lang.org/book/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;The Book&lt;/a&gt; and started using it for some mini projects.&lt;/p&gt;
&lt;p&gt;But this time I didn&amp;#x27;t feel productive enough to actually start building with it. I &lt;em&gt;could&lt;/em&gt; get programs to work by pattern matching and trying things somewhat randomly to appease the compiler, but it didn&amp;#x27;t feel like I knew what was really going on. It was a while back, but I felt that The Book didn&amp;#x27;t quite have a specific audience in mind and tended to distribute time to topics unevenly in relation to their difficulty.&lt;/p&gt;
&lt;h2&gt;Attempt 2: A hobby project&lt;/h2&gt;
&lt;p&gt;A number of people mentioned how they eventually got productive by just writing more rust, so I thought I would try that by using it for a big project.&lt;/p&gt;
&lt;p&gt;One of my favorite projects is ray tracing, ever since I learned how it works in &lt;a href=&quot;https://www.povray.org/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;POV-Ray&lt;/a&gt;&amp;#x27;s manual (where they &lt;a href=&quot;https://www.povray.org/documentation/3.7.0/t2_3.html#t2_3_11&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;build a ray tracer &lt;em&gt;within&lt;/em&gt; POV-Ray&lt;/a&gt; using its meta language), converted it into a C++ program and rendered it in glorious &lt;code class=&quot;&quot;&gt;800x600x24&lt;/code&gt; resolution via extended &lt;a href=&quot;https://en.wikipedia.org/wiki/Mode_13h&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Mode 13h&lt;/a&gt;. I still cannot help but be amazed that a bit of high school level math can produce such realistic images. So I thought it would be fun to write one in Rust.&lt;/p&gt;
&lt;p&gt;I wrote a very basic spheres-only version in July 2022 and got it to do multi-threaded rendering in about 5 days. This was substantial enough to actually feel productive, and a testament to Rust&amp;#x27;s design that adding correct concurrency was not particularly difficult. I was even more impressed when I swapped out my multi-threading code with the &lt;code class=&quot;&quot;&gt;crayon&lt;/code&gt; library&amp;#x27;s parallel iterator.&lt;/p&gt;
&lt;p&gt;However, the raytracer was pretty limited at this point. There&amp;#x27;s only so much you can render with matte spheres:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://shreyb.dev/assets/raytraced-logo.png&quot; loading=&quot;lazy&quot; alt=&quot;A raytraced image of some spheres shaped like the Google logo&quot;/&gt;&lt;/p&gt;
&lt;p&gt;So I opened up the &lt;a href=&quot;https://www.pbr-book.org/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;PBR book&lt;/a&gt; and slowly added more features while keeping my day job. While I was learning a number of things around this time (like &lt;a href=&quot;https://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Importance_Sampling#MultipleImportanceSampling&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;multiple importance sampling&lt;/a&gt; and &lt;a href=&quot;https://www.pbr-book.org/3ed-2018/Color_and_Radiometry/Radiometry&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Radiometry&lt;/a&gt;), I wasn&amp;#x27;t learning much Rust.&lt;/p&gt;
&lt;h3&gt;It looks like you are trying to write a program&lt;/h3&gt;
&lt;p&gt;In 2023, I had a break from work and had a lot more time to spend on it. At this point, &lt;a href=&quot;https://github.com/features/copilot&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;GitHub Copilot&lt;/a&gt; had come into being and I enabled it for this project. It had two interesting effects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It was good at filling in the obvious and repetitive code that needs to be written in graphics, like repeating a calculation for &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;, &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;z&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; dimensions.&lt;/li&gt;
&lt;li&gt;It would sometimes show me new features of rust that I was not aware of.
With its help, I managed to even write a parser for a custom scene file format for the raytracer, with some particularly &lt;a href=&quot;https://github.com/banga/craytracer/blob/4820473911886343cc737bf0cc639e55efc89b86/src/scene_parser.rs#L724-L748&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;clever&lt;/a&gt; logic to make it concise and extensible.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However, while it made me feel more productive and let me focus on figuring out the trickier aspects of raytracing, I realized that my understanding of rust wasn&amp;#x27;t getting particularly clearer. So I eventually disabled it and decided to learn it the old fashioned way.&lt;/p&gt;
&lt;h2&gt;Attempt 3: Read a book&lt;/h2&gt;
&lt;p&gt;I picked up the &lt;a href=&quot;https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Programming Rust, 2nd Edition&lt;/a&gt; ebook, which seemed to be the most common recommendation. I made my way through it slowly at first but I started to notice that I was &amp;quot;getting it&amp;quot; more now. It&amp;#x27;s hard to say whether this was a result of better writing or having had more practice with it, but it didn&amp;#x27;t take long to realize that the book was clearing the fog. I definitely felt that the authors were good at realizing which parts deserved more elaboration and which didn&amp;#x27;t.&lt;/p&gt;
&lt;p&gt;Around this time, I left my job and took a complete break from programming. Then around the end of 2023, after I did &lt;a href=&quot;https://adventofcode.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Advent of Code&lt;/a&gt; in Rust, I got a second wind and started reading the book again. As I learned things I could use in the raytracer, I would go back and &lt;a href=&quot;https://github.com/banga/craytracer/commit/9ff0d0498ad5524cd5ae4c2e16d4dcb47980a9a8&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;apply&lt;/a&gt; &lt;a href=&quot;https://github.com/banga/craytracer/commit/e31a0249d15c1c614d61d7b11ed83350b7accf0f&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;them&lt;/a&gt; &lt;a href=&quot;https://github.com/banga/craytracer/commit/6b92724ebc8740685312d92c3d67bebda5ccabc7&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;to&lt;/a&gt; it. I eventually once again got distracted by the graphics and added several sophisticated features to get to the point of rendering images like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://shreyb.dev/assets/staircase.png&quot; loading=&quot;lazy&quot; alt=&quot;A raytraced image of a staircase with textures, area lighting&quot;/&gt;
&lt;em&gt;&lt;a href=&quot;https://blendswap.com/blend/14449&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;The Wooden Staircase&lt;/a&gt; by &lt;a href=&quot;https://blendswap.com/profile/130393&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Wig42&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Anyway, I did finish the book once the raytracing side quest was done (for now). While there are a few chapters that will need a revisit when I actually need to use them (Async, FFI, unsafe rust), I ended it feeling a lot more comfortable with the language.&lt;/p&gt;
&lt;p&gt;For the most recent work I did in the language, I felt nearly as productive as I had previously in TypeScript or Python&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Rust is a vast language and sometimes the safety checks &lt;em&gt;can&lt;/em&gt; get quite onerous, so I&amp;#x27;m sure I won&amp;#x27;t always feel this optimistic about it, but it&amp;#x27;s nice to not be intimidated by a popular systems level language anymore.&lt;/p&gt;
&lt;section data-footnotes=&quot;true&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I was equally disheartened and delighted to later learn that the simple mental model I had for the cpu and memory were yet further from reality. Compiler optimizations, pipelining, branch prediction, out of order execution etc. were all fascinating and slightly terrifying things to learn about. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Especially when the GC comes a knockin&amp;#x27;. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;Each of these languages excel in their own domains, so perhaps this isn&amp;#x27;t totally accurate. I wouldn&amp;#x27;t be as productive building websites in Rust as I would be in TypeScript, but the opposite is true for writing, say, a database. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
    </entry>
<entry>
      <title>The rocket equation for startups</title>
      <link href="https://shreyb.dev/blog/2024/01/09/startup-rocket-equation.html" />
      <updated>2024-01-09T00:00:00.000Z</updated>
      <id>https://shreyb.dev/blog/2024/01/09/startup-rocket-equation.html</id>
      <author>
        <name>Shrey Banga</name>
      </author>
      <content type="html">&lt;h1&gt;The rocket equation for startups&lt;/h1&gt;
&lt;p&gt;Startups love being compared to rocket ships. Let&amp;#x27;s take that analogy where it has never gone before.&lt;/p&gt;
&lt;h2&gt;The tyranny of the equation&lt;/h2&gt;
&lt;p&gt;For the unfamiliar, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Tsiolkovsky_rocket_equation&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;rocket equation&lt;/a&gt; describes how much total mass (&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;) your rocket will be if you want to get a payload of a given mass (&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;) up to a given velocity (&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Δ&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\Delta v&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;), if the exhaust velocity of the fuel is &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;v_e&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;. It turns out to be exponential, which makes going to space quite expensive:&lt;/p&gt;
&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mtable rowspacing=&quot;0.25em&quot; columnalign=&quot;right&quot; columnspacing=&quot;&quot;&gt;&lt;mtr&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/msub&gt;&lt;msup&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Δ&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mtext&gt;e&lt;/mtext&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mml-eqn-num&quot;&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\begin{align}
m_t = m_f e^{\Delta v / v_\text{e}}
\end{align}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;
&lt;p&gt;In plainer words, to carry some stuff to space, you need to carry some fuel, but to carry &lt;em&gt;that&lt;/em&gt; fuel, you need to carry some more fuel, and so on. To leave the gravitational pull of a planet, you need to reach a minimum velocity, called the &lt;em&gt;escape velocity&lt;/em&gt;. As the required velocity increases, the required mass increases exponentially.&lt;/p&gt;
&lt;p&gt;When an organization hires more people to do more work, it must also hire some people to support these new people, who in turn might need to be supported by a few more new people, and so on. If you take the rocket analogy literally, the size of the organization must grow exponentially relative to the amount of work that needs to be done.&lt;/p&gt;
&lt;p&gt;If you have worked at a rapidly growing startup, you have probably experienced this. You spend ever more effort hiring and training people, and yet there are never enough people to work on everything and support everyone. In the extreme case, it can feel like a paradoxical machine where everyone is busy hiring and training new people so &lt;em&gt;they&lt;/em&gt; can get the work done that no one is doing because everyone is busy hiring.&lt;/p&gt;
&lt;h2&gt;How to leave the gravity well&lt;/h2&gt;
&lt;p&gt;Startups of course don&amp;#x27;t usually&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; want to grow their size exponentially. Still taking the equation quite literally, there are a few ways around it:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use more efficient fuel&lt;/strong&gt;. There are many ways to translate this: hire people who need less support. Focus on doing fewer things. Sell to bigger customers.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Build on free technology and content.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; Hire generalists who can fill multiple roles.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lower the escape velocity&lt;/strong&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot; id=&quot;user-content-fnref-4&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. If we take escape velocity to mean survival of the company, lowering it could mean picking a different business plan, a different mechanism of funding, or pivoting to a market with a lower floor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Launch smaller rockets&lt;/strong&gt;. This doesn&amp;#x27;t relieve you of the exponential growth rate, but it gives you more attempts at finding the parameters of a successful launch. This is more commonly deployed &lt;em&gt;after&lt;/em&gt; an organization is feeling the effects of rapid growth. Tiger teams, two pizza teams, moonshots, 20% time, hack days etc. are all variants on the same desire – send out smaller rockets and see which ones make it.&lt;/p&gt;
&lt;h2&gt;Back on planet earth&lt;/h2&gt;
&lt;p&gt;As promised, I&amp;#x27;ve stretched the analogy to &lt;a href=&quot;https://en.wikipedia.org/wiki/Max_q&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;max q&lt;/a&gt;. It amused me how far it held up as I was noodling with it, so I wrote it down. Hopefully, next time someone offers you a seat on a rocket ship, this will inspire a little chuckle.&lt;/p&gt;
&lt;section data-footnotes=&quot;true&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;Pre-2023, some startups did appear to be manifesting their higher valuations by hiring a lot of people very quickly. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;Most tech companies attempt a pivot to selling to big enterprises sooner or later. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Arguably, many of the largest consumer software companies succeeded by figuring out novel ways to extract value from information and technology that was shared for free by someone. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-4&quot;&gt;
&lt;p&gt;Interestingly, since escape velocity is independent of mass, load-shedding (i.e. layoffs) does not actually lower it. &lt;a href=&quot;#user-content-fnref-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
    </entry>
<entry>
      <title>I spent way too long building this blog</title>
      <link href="https://shreyb.dev/blog/2023/12/23/building-this-blog.html" />
      <updated>2023-12-23T00:00:00.000Z</updated>
      <id>https://shreyb.dev/blog/2023/12/23/building-this-blog.html</id>
      <author>
        <name>Shrey Banga</name>
      </author>
      <content type="html">&lt;h1&gt;I spent way too long building this blog&lt;/h1&gt;
&lt;p&gt;...and must therefore write about it to alleviate the guilt.&lt;/p&gt;
&lt;h2&gt;Hiding from Dr. Jekyll&lt;/h2&gt;
&lt;p&gt;As you can probably tell, this blog has been inactive since the peak of March 2020, where I apparently reacted to the pandemic with a surge in creativity.&lt;/p&gt;
&lt;p&gt;Back then, the blog was hosted on &lt;a href=&quot;https://pages.github.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;GitHub pages&lt;/a&gt;, which used &lt;a href=&quot;https://jekyllrb.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Jekyll&lt;/a&gt; to build and serve the blog from a set of markdown files. This was fine to start with, but it used a lot of unfamiliar tech (Ruby, Liquid, markdown extensions) that made it difficult to configure and maintain. It soon bit rotted enough to discourage me from writing in the fleeting moments of inspiration.&lt;/p&gt;
&lt;p&gt;I have been taking a break from programming for the past few months and as I return from it to start a job search, I thought I should clean up my online presence. So I decided it was finally time to replace the Jekyll setup.&lt;/p&gt;
&lt;p&gt;My initial investigation revealed that GitHub now allows you to deploy pages using GitHub Actions, so you can pick from a plethora of static site generators. However, this time I wanted something very minimal that I could jump back into a year from now and not get bogged down reading outdated docs and updating dependencies.&lt;/p&gt;
&lt;p&gt;So, I decided it was finally time to enter the rite of passage that is writing a tool to generate your website.&lt;/p&gt;
&lt;h2&gt;Making a list, checking it twice&lt;/h2&gt;
&lt;p&gt;Such projects go a lot better if I have a clear idea of what I want from them. Otherwise, I spend way too much time playing with the tech and not enough building the thing that needs to exist.&lt;/p&gt;
&lt;p&gt;I had a rough idea that I wanted a fast, minimal, modern site that introduces myself and hosts my writing. I imagined expanding it out over time to link to more details about my work and side projects.&lt;/p&gt;
&lt;p&gt;My previous home page was a small 3d business card&lt;sup&gt;&lt;a href=&quot;#user-content-fn-home-archive&quot; id=&quot;user-content-fnref-home-archive&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; that didn&amp;#x27;t link to my blog&lt;sup&gt;&lt;a href=&quot;#user-content-fn-blog-archive&quot; id=&quot;user-content-fnref-blog-archive&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. The site and the blog were hosted via separate GitHub repos, where the home page was just a static site and the blog was generated by Jekyll.&lt;/p&gt;
&lt;p&gt;There were a number of things I liked about the old blog — posts authored in markdown&lt;sup&gt;&lt;a href=&quot;#user-content-fn-on-markdown&quot; id=&quot;user-content-fnref-on-markdown&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, footnotes, math, syntax-highlighting, heading permalinks, dates in urls, autogenerated RSS feed, SEO and OpenGraph tags etc.&lt;/p&gt;
&lt;p&gt;So I made a checklist of the features I wanted in the new setup and got cracking.&lt;/p&gt;
&lt;h2&gt;First, we prototype...&lt;/h2&gt;
&lt;p&gt;I first wanted to see how feasible it was to write something that could generate a site with similar functionality without the same complexity as before.&lt;/p&gt;
&lt;p&gt;My plan was to find a way to convert the markdown content of posts to html, wrap it in some scaffolding to form a valid html document and save that to a static directory that the public site could be served from. Even better if this could be done automatically in a GitHub Action.&lt;/p&gt;
&lt;p&gt;I have been learning Rust lately and using it for &lt;a href=&quot;https://adventofcode.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Advent of Code&lt;/a&gt;, so I briefly wondered if I should use it for this project as well. I decided against it quickly, because so far it hasn&amp;#x27;t proved great for prototyping and the ecosystem of markdown related tooling was much bigger in JS.&lt;/p&gt;
&lt;p&gt;So I started with a node+TypeScript project. I used &lt;a href=&quot;https://remarkjs.github.io/react-markdown/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;react-markdown&lt;/a&gt; (which uses &lt;a href=&quot;https://github.com/unifiedjs/unified&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;unifiedjs&lt;/a&gt; and plugins) to parse the markdown posts, wrapped them in a component and serialized them to corresponding html files.&lt;/p&gt;
&lt;p&gt;For styling, I like the utility file approach&lt;sup&gt;&lt;a href=&quot;#user-content-fn-css-utility-file&quot; id=&quot;user-content-fnref-css-utility-file&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; of writing out generic classes like &lt;code class=&quot;&quot;&gt;.font-small&lt;/code&gt; and using those to style components. We used this approach at Airtable and it felt much more productive than the traditional approach of using CSS. I created one from scratch, allowing that I might switch over to a framework, but didn&amp;#x27;t want the overhead from the start.&lt;/p&gt;
&lt;p&gt;With that, I had a tool that could generate blog posts to my liking and enough confidence that this was worth building out.&lt;/p&gt;
&lt;h2&gt;...then draw rest of the owl&lt;/h2&gt;
&lt;p&gt;A bunch of the remaining work was just setting up the code as a script that could generate the full site with some configurable parameters like the host name (for local testing) and the posts directory (so I could store drafts separately). I&amp;#x27;ll skip those boring details, but there &lt;em&gt;were&lt;/em&gt; a few fun things along the way:&lt;/p&gt;
&lt;h3&gt;Deploying to GitHub Pages&lt;/h3&gt;
&lt;p&gt;I remembered finding the original process for deploying a GitHub Pages website quite confusing. Digging around into the source code of various GitHub actions demystified it a lot. I started with &lt;a href=&quot;https://github.com/actions/starter-workflows/blob/main/pages/static.yml&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; action that deploys a static directory and modified it to run a build step first. This pretty much worked the first time, partly out of luck because I was placing my generated files in &lt;code class=&quot;&quot;&gt;_site/&lt;/code&gt; (a holdover from Jekyll) and the &lt;code class=&quot;&quot;&gt;upload-pages-artifact&lt;/code&gt; action defaults to picking up the content from that folder.&lt;/p&gt;
&lt;h3&gt;Generating preview images for OpenGraph&lt;/h3&gt;
&lt;p&gt;One of the useful things Jekyll generated was metadata for search engines and social networks to help surface your content properly. Those were fairly easy to figure out since I already had the relevant metadata from posts. While looking at other blogs for some inspiration, I noticed that &lt;a href=&quot;https://rauchg.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Guillermo Rauch&amp;#x27;s blog&lt;/a&gt; had an &lt;code class=&quot;&quot;&gt;&amp;lt;og:image content=&amp;quot;...&amp;quot;&amp;gt;&lt;/code&gt; tag as well, which Jekyll did not generate.&lt;/p&gt;
&lt;p&gt;On opening the linked URL, I realized that this was meant for the preview image in social networks, such as this one for an issue on GitHub:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://shreyb.dev/assets/github-pr-preview-example.png&quot; loading=&quot;lazy&quot; alt=&quot;Image showing the preview of a Github issue on a social network&quot;/&gt;&lt;/p&gt;
&lt;p&gt;This was too charming to not implement. I knew that generating screenshots of websites on the backend is a pain&lt;sup&gt;&lt;a href=&quot;#user-content-fn-server-side-screenshots&quot; id=&quot;user-content-fnref-server-side-screenshots&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; because it usually involves either downloading a headless browser or a combination of DOM emulation and serialization libraries, neither of which screams maintainability.&lt;/p&gt;
&lt;p&gt;However, on a closer look at &lt;code class=&quot;&quot;&gt;rauchg&lt;/code&gt;&amp;#x27;s blog, I realized that it was using their &lt;a href=&quot;https://vercel.com/docs/functions/edge-functions/og-image-generation&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Open Graph Image Generation&lt;/a&gt; edge function, which in turn uses &lt;a href=&quot;https://github.com/vercel/satori&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Satori&lt;/a&gt; that has (limited) support for rendering DOM elements on the backend using wasm+JS. This worked like a charm&lt;sup&gt;&lt;a href=&quot;#user-content-fn-satori-ty&quot; id=&quot;user-content-fnref-satori-ty&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, with the only annoyance being that I had to duplicate some of my CSS as inline styles. I left a little TODO to figure out how to share these styles, perhaps via &lt;a href=&quot;https://www.npmjs.com/package/css-inliner&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;css-inliner&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Generating permalinks to headings&lt;/h3&gt;
&lt;p&gt;One thing I&amp;#x27;ve comed to love from working at and using &lt;a href=&quot;https://quip.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Quip&lt;/a&gt; is deep linking to documents (which lets you do so to any paragraph). It&amp;#x27;s a great way to share deeply embedded information in context and build out a knowledge graph. GitHub has a particularly nice approach about this where they automatically create anchor links for headings in the document, such as &lt;a href=&quot;https://github.com/banga/git-split-diffs/tree/main#themes&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;https://github.com/banga/git-split-diffs/tree/main#themes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the Jekyll setup, I was using some plugin that required manually writing out ids in curly brackets next to headings, like&lt;/p&gt;
&lt;pre&gt;&lt;pre class=&quot;shiki shiki-themes vitesse-light github-dark&quot; style=&quot;--shiki-light:#393a34;--shiki-dark:#e1e4e8;--shiki-light-bg:#ffffff;--shiki-dark-bg:#24292e&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#79B8FF;--shiki-light-font-weight:bold;--shiki-dark-font-weight:bold&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#1C6B48;--shiki-dark:#79B8FF;--shiki-light-font-weight:bold;--shiki-dark-font-weight:bold&quot;&gt; Smart Selection {#smart-selection}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;to generate a permalink. I much prefer GitHub&amp;#x27;s approach. I looked at the plugins for &lt;code class=&quot;&quot;&gt;react-markdown&lt;/code&gt; but didn&amp;#x27;t find anything that worked this way, so wrote something based on &lt;a href=&quot;https://github.com/remarkjs/react-markdown/issues/404#issuecomment-604019030&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; suggestion in an issue thread:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;&quot;&gt;react-markdown&lt;/code&gt; allows you to override rendering of specific HTML tags via the &lt;code class=&quot;&quot;&gt;components&lt;/code&gt; prop. I wrote a component that would replace the default renderer for heading elements, had it parse the contents of the heading, generate an id from that and then insert a link next to the heading. With a touch of CSS to only show these links on hover, this was ready to use.&lt;/p&gt;
&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a gotcha with these links called &lt;a href=&quot;https://en.wikipedia.org/wiki/DOM_clobbering&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;DOM clobbering&lt;/a&gt; because these links use an &lt;code class=&quot;&quot;&gt;id&lt;/code&gt; attribute, which automatically exposes said element to the &lt;code class=&quot;&quot;&gt;window&lt;/code&gt; global. However, since I don&amp;#x27;t plan on hosting any external JS&lt;sup&gt;&lt;a href=&quot;#user-content-fn-no-js&quot; id=&quot;user-content-fnref-no-js&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; or sensitive content here, I&amp;#x27;m giving it a pass.&lt;/p&gt;
&lt;h3&gt;Rendering math&lt;/h3&gt;
&lt;p&gt;My last post made heavy use of math using &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext&gt;LaTeX&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\LaTeX&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; notation, which I wanted to preserve. Thankfully, there are multiple &lt;a href=&quot;https://github.com/unifiedjs/unified&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;unifiedjs&lt;/a&gt; plugins that can parse and render math in markdown. I initially picked &lt;a href=&quot;https://www.npmjs.com/package/remark-math&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;remark-math&lt;/a&gt; and &lt;a href=&quot;https://www.npmjs.com/package/rehype-mathjax&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;rehype-mathjax&lt;/a&gt;, which rendered correctly on the web.&lt;/p&gt;
&lt;p&gt;Later, when I was &lt;a href=&quot;#generating-a-blog-feed&quot; node=&quot;[object Object]&quot;&gt;generating a blog feed&lt;/a&gt;, I noticed that the tags used by MathJax were not rendering in feed readers. This took some delicate fixing, because feed readers don&amp;#x27;t seem to support evicting their caches. So I had to dust off my old &lt;a href=&quot;https://theoldreader.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;The Old Reader&lt;/a&gt; and &lt;a href=&quot;https://www.newsblur.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;NewsBlur&lt;/a&gt; accounts. I replaced &lt;a href=&quot;https://www.npmjs.com/package/rehype-mathjax&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;rehype-mathjax&lt;/a&gt; with &lt;a href=&quot;https://www.npmjs.com/package/rehype-katex&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;rehype-katex&lt;/a&gt;, which uses &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/MathML&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;MathML&lt;/a&gt; tags that finally have cross browser support in 2023&lt;sup&gt;&lt;a href=&quot;#user-content-fn-mathml-ty&quot; id=&quot;user-content-fnref-mathml-ty&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; and seem to render fine in feed aggregators.&lt;/p&gt;
&lt;h3&gt;Syntax highlighting code blocks&lt;/h3&gt;
&lt;p&gt;I shared a few code snippets before, which were highlighted by Jekyll by default using &lt;a href=&quot;https://pygments.org/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Pygments&lt;/a&gt;. I wanted to improve on that by rendering it in VS Code&amp;#x27;s dark theme, having written a &lt;a href=&quot;https://github.com/banga/git-split-diffs?tab=readme-ov-file#git-split-diffs&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;tool to do the same on the terminal&lt;/a&gt;. I used &lt;a href=&quot;https://github.com/react-syntax-highlighter/react-syntax-highlighter&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;react-syntax-highlighter&lt;/a&gt;, which delegates to &lt;a href=&quot;https://prismjs.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Prism&lt;/a&gt;. It&amp;#x27;s not identical, but it ships with a theme called &lt;code class=&quot;&quot;&gt;vsc-dark-plus&lt;/code&gt; that replicates VS Code&amp;#x27;s &lt;code class=&quot;&quot;&gt;Dark+&lt;/code&gt; theme. Loading this theme was a bit of a pain in my node ESM setup, partly because the types shipped with react-syntax-highlighter are &lt;a href=&quot;https://arethetypeswrong.github.io/?p=react-syntax-highlighter%4015.5.0&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;wrong&lt;/a&gt;, but it worked fine after that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;: I have since &lt;a href=&quot;https://github.com/banga/banga.github.io/commit/42abb7c81502b9227223ca63577ce17816c3ffe5&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;replaced&lt;/a&gt; &lt;code class=&quot;&quot;&gt;react-syntax-highlighter&lt;/code&gt; with &lt;a href=&quot;https://shikiji.netlify.app/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;shikiji&lt;/a&gt;, which renders accurate VS Code themes.&lt;/p&gt;
&lt;h3&gt;Rendering footnotes&lt;/h3&gt;
&lt;p&gt;My last post really went all out on all the github extensions it could use, which included footnotes. Thankfully, these were easy to support, via the &lt;a href=&quot;https://github.com/remarkjs/remark-gfm&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;remark-gfm&lt;/a&gt; plugin. It actually pulls in a number of features from &lt;a href=&quot;https://github.github.com/gfm/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;GitHub Flavored Markdown&lt;/a&gt; apart from footnotes, such as strikethroughs, tables and task lists. These will come in handy in the future.&lt;/p&gt;
&lt;h3&gt;Generating a blog feed&lt;/h3&gt;
&lt;p&gt;I use &lt;a href=&quot;https://feedly.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Feedly&lt;/a&gt; to follow other blogs and hopefully someone will want to follow mine some day. So I wanted to generate a feed for my posts as well. I sampled the feeds for a few blogs I read recently (&lt;a href=&quot;https://v8.dev/blog&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;v8&lt;/a&gt;, &lt;a href=&quot;https://kvakil.me/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Keyhan&amp;#x27;s blog&lt;/a&gt;, &lt;a href=&quot;https://blog.persistent.info/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Mihai&amp;#x27;s blog&lt;/a&gt;). Between RSS and Atom, I found the Atom format slightly easier to write. Other than the math rendering hiccup mentioned earlier, this worked easily.&lt;/p&gt;
&lt;h3&gt;Auto reloading&lt;/h3&gt;
&lt;p&gt;My last bit of indulgence in this project was to add auto reloading. My workflow so far had been to run the build script in watch mode via &lt;a href=&quot;https://nodemon.io/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;nodemon&lt;/a&gt;, serve the output using &lt;code class=&quot;&quot;&gt;npx http-server ./_site&lt;/code&gt; and then hard refresh pages to see my changes.&lt;/p&gt;
&lt;p&gt;This worked fine, but I have seen a few too many auto/hot reloading demos to be satisfied with it. A fast feedback loop during development and design makes iterative improvements that much easier. Reading a well formatted web page also beats reading markdown.&lt;/p&gt;
&lt;p&gt;The usual approach for this works by having the client talk to a server (usually via a &lt;code class=&quot;&quot;&gt;WebSocket&lt;/code&gt;), which watches the inputs and sends a message to the client when the relevant inputs change.&lt;/p&gt;
&lt;p&gt;I didn&amp;#x27;t want to add the complexity of setting up my own server, so I took a different approach. My build script writes out a hash file at the end of the build containing the content hash of everything in the output directory. The client polls this file and reloads if the contents change. The only thing it relies on from the server is to not cache the contents of the static directory. This is achieved by passing the &lt;code class=&quot;&quot;&gt;-c-1&lt;/code&gt; flag to &lt;code class=&quot;&quot;&gt;http-server&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#x27;m pretty pleased with the result as I type this and hit save.&lt;/p&gt;
&lt;h2&gt;Too long, didn&amp;#x27;t read?&lt;/h2&gt;
&lt;p&gt;That&amp;#x27;s ok. This is mostly for my own documentation when I look back and wonder how to get this thing working again. I also found and corrected a couple of issues in the process of writing this.&lt;/p&gt;
&lt;p&gt;It also dawned on me as I wrote this down that even a dinky little website like this relies on an absurd amount of engineering and creativity by often thankless volunteers.&lt;/p&gt;
&lt;p&gt;So, if you are one of those who share their work for free, thank you. The source for this repository is available at &lt;a href=&quot;https://github.com/banga/banga.github.io&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;banga/banga.github.io&lt;/a&gt;&lt;/p&gt;
&lt;section data-footnotes=&quot;true&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-home-archive&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20220203233535/https://banga.github.io/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;https://web.archive.org/web/20220203233535/https://banga.github.io/&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-home-archive&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-blog-archive&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20230126105442/https://banga.github.io/blog/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;https://web.archive.org/web/20230126105442/https://banga.github.io/blog/&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-blog-archive&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-on-markdown&quot;&gt;
&lt;p&gt;I generally don&amp;#x27;t like markdown as a storage format or API surface, largely because it&amp;#x27;s not really a standard, but it works fine for an authorship of one. &lt;a href=&quot;#user-content-fnref-on-markdown&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-css-utility-file&quot;&gt;
&lt;p&gt;I don&amp;#x27;t know if there&amp;#x27;s an actual name for this style, is there? &lt;a href=&quot;#user-content-fnref-css-utility-file&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-server-side-screenshots&quot;&gt;
&lt;p&gt;Many web apps do this in their export and print flows, because rendering to an image is often more reliable and easier to customize than client-side printing in browsers. &lt;a href=&quot;#user-content-fnref-server-side-screenshots&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-satori-ty&quot;&gt;
&lt;p&gt;Thank you vercel for open sourcing this and WASM for making it possible! &lt;a href=&quot;#user-content-fnref-satori-ty&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 6&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-no-js&quot;&gt;
&lt;p&gt;In fact, no JS at all so far. &lt;a href=&quot;#user-content-fnref-no-js&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 7&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-mathml-ty&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.igalia.com/2023/01/10/Igalia-Brings-MathML-Back-to-Chromium.html&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;https://www.igalia.com/2023/01/10/Igalia-Brings-MathML-Back-to-Chromium.html&lt;/a&gt;. “This is the first example I know of that a major, major feature is really coming to the Web despite there not really being a business case for the business that normally advance the Web,” said Rick Byers of the Chrome team at Google. Many thanks to the volunteers! &lt;a href=&quot;#user-content-fnref-mathml-ty&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 8&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
    </entry>
<entry>
      <title>What's the smallest country that can fit everyone standing six feet apart?</title>
      <link href="https://shreyb.dev/blog/2020/03/28/smallest-country-that-can-fit-everyone-six-feet-apart.html" />
      <updated>2020-03-28T00:00:00.000Z</updated>
      <id>https://shreyb.dev/blog/2020/03/28/smallest-country-that-can-fit-everyone-six-feet-apart.html</id>
      <author>
        <name>Shrey Banga</name>
      </author>
      <content type="html">&lt;h1&gt;What&amp;#x27;s the smallest country that can fit everyone standing six feet apart?&lt;/h1&gt;
&lt;p&gt;Today&amp;#x27;s &lt;a href=&quot;https://xkcd.com/2286/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;xkcd&lt;/a&gt; got me wondering how much land would we
need if everyone stood six feet apart.&lt;/p&gt;
&lt;h2&gt;Methodology&lt;/h2&gt;
&lt;h3&gt;We are all but spherical cows&lt;/h3&gt;
&lt;p&gt;If we want everyone to keep a minimum distance of &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; from each other, the
problem boils down to efficiently packing &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; circles of radius &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; in the
smallest area possible. This can be calculated as follows:&lt;/p&gt;
&lt;p&gt;Area of a circle with radius &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;,&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;π&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;A_r = \pi r^2 &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Optimal circle packing density&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;,&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;π&lt;/mi&gt;&lt;msqrt&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msqrt&gt;&lt;/mrow&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\eta  = \frac{\pi\sqrt{3}}{6}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Area required for &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt; people,&lt;/p&gt;
&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mtable rowspacing=&quot;0.25em&quot; columnalign=&quot;right left&quot; columnspacing=&quot;0em&quot;&gt;&lt;mtr&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;msub&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mfrac&gt;&lt;msub&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;η&lt;/mi&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mml-eqn-num&quot;&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;π&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;π&lt;/mi&gt;&lt;msqrt&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msqrt&gt;&lt;/mrow&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;/mfrac&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mml-eqn-num&quot;&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;msqrt&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msqrt&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mml-eqn-num&quot;&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\begin{align}
    A_n &amp;amp; = n \cdot \frac{A_r}{\eta} \\
        &amp;amp; = n \cdot \frac{\pi r^2}{\frac{\pi \sqrt{3}}{6}} \\
        &amp;amp; = 2 \sqrt{3} \cdot n \cdot r^2
\end{align}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;
&lt;h3&gt;Crunching the numbers&lt;/h3&gt;
&lt;p&gt;Plugging in the current world population&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and the recommended distance of 6 feet&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext&gt;7,773,861,168&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;n = \text{7,773,861,168}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;mtext&gt;ft&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;r = 6\text{ft}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;we get&lt;/p&gt;
&lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mtable rowspacing=&quot;0.25em&quot; columnalign=&quot;right left&quot; columnspacing=&quot;0em&quot;&gt;&lt;mtr&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;msub&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/msub&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;9.695&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;msup&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mn&gt;11&lt;/mn&gt;&lt;/msup&gt;&lt;msup&gt;&lt;mtext&gt;ft&lt;/mtext&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mml-eqn-num&quot;&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd&gt;&lt;mstyle scriptlevel=&quot;0&quot; displaystyle=&quot;true&quot;&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;34&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;775&lt;/mn&gt;&lt;msup&gt;&lt;mtext&gt;mi&lt;/mtext&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;/mstyle&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mtr-glue&quot;&gt;&lt;/mtd&gt;&lt;mtd class=&quot;mml-eqn-num&quot;&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\begin{align}
    A_n &amp;amp; = 9.695×10^{11} \text{ft}^2 \\
        &amp;amp; = 34,775 \text{mi}^2 \\
\end{align}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;
&lt;h3&gt;And the answer is...&lt;/h3&gt;
&lt;p&gt;According to Wikipedia&lt;sup&gt;&lt;a href=&quot;#user-content-fn-4&quot; id=&quot;user-content-fnref-4&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, this is just shy of the land area of &lt;strong&gt;Portugal 🇵🇹&lt;/strong&gt;.
We could also squeeze into &lt;strong&gt;Hungary 🇭🇺&lt;/strong&gt; if some of us were willing to swim.&lt;/p&gt;
&lt;h2&gt;Corollaries&lt;/h2&gt;
&lt;h3&gt;How many people can San Francisco fit standing 6 feet apart?&lt;/h3&gt;
&lt;p&gt;Dividing the area of San Francisco by &lt;span class=&quot;katex&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;msqrt&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msqrt&gt;&lt;mo&gt;⋅&lt;/mo&gt;&lt;mn&gt;36&lt;/mn&gt;&lt;msup&gt;&lt;mtext&gt;ft&lt;/mtext&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2 \sqrt{3} \cdot 36 \text{ft}^2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;, gives
us around &lt;strong&gt;10.5 million&lt;/strong&gt; people.&lt;/p&gt;
&lt;h3&gt;Are there any countries where people couldn&amp;#x27;t stand 6 feet apart?&lt;/h3&gt;
&lt;p&gt;1 square mile of land can have 223,563 people standing 6 feet apart. This is
much higher than the most densely populated countries and territories in the
world&lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot; id=&quot;user-content-fnref-5&quot; data-footnote-ref=&quot;true&quot; aria-describedby=&quot;footnote-label&quot; node=&quot;[object Object]&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;section data-footnotes=&quot;true&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Circle_packing&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Circle packing - Wikipedia&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.worldometers.info/world-population/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Current World Population - Worldometers&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cdc.gov/coronavirus/2019-ncov/prepare/prevention.html&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Prevention of Coronavirus Disease 2019 (COVID-19) - CDC&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-4&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_area&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;List of countries and dependencies by area - Wikipedia&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-5&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_population_density&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;List of countries and dependencies by population density - Wikipedia&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot; class=&quot;data-footnote-backref&quot; node=&quot;[object Object]&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
    </entry>
<entry>
      <title>Syncing dev environments the hard way</title>
      <link href="https://shreyb.dev/blog/2020/03/07/syncing-dev-environments-the-hard-way.html" />
      <updated>2020-03-07T00:00:00.000Z</updated>
      <id>https://shreyb.dev/blog/2020/03/07/syncing-dev-environments-the-hard-way.html</id>
      <author>
        <name>Shrey Banga</name>
      </author>
      <content type="html">&lt;h1&gt;Syncing dev environments the hard way&lt;/h1&gt;
&lt;p&gt;If you use multiple machines for development, you probably run into the problem of keeping your dev environments in sync. For example, say your coworker introduced you to &lt;a href=&quot;https://github.com/junegunn/fzf&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;fzf&lt;/a&gt; and you installed it on your work machine. Wouldn&amp;#x27;t it be nice if it was also installed on your machine at home when you opened it?&lt;/p&gt;
&lt;p&gt;Some of these changes only require sharing dotfiles (e.g. &lt;code class=&quot;&quot;&gt;.bashrc&lt;/code&gt; or &lt;code class=&quot;&quot;&gt;.zshrc&lt;/code&gt;) which is simple enough to do via something like Dropbox. However, I wanted to sync much more, like my zsh plugins, vscode extensions, Mac apps, fonts etc.&lt;/p&gt;
&lt;p&gt;Luckily, I enjoy spending hours of programming to save minutes of future drudgery. The solution I landed on (inspired by &lt;a href=&quot;https://github.com/mathiasbynens/dotfiles&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;mathiasbynens/dotfiles&lt;/a&gt;) is a Github repo with files that describe the environment and a script that makes sure the environment matches them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://shreyb.dev/assets/dotfiles-update.gif&quot; loading=&quot;lazy&quot; alt=&quot;Gif showing the sync script running&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The rest of this post describes my setup in detail, but if you just want the repo, check out &lt;a href=&quot;https://github.com/banga/dotfiles-template&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;banga/dotfiles-template&lt;/a&gt;. It&amp;#x27;s a cleaned-up version of my personal setup that you can just clone and customize.&lt;/p&gt;
&lt;h2&gt;How this works&lt;/h2&gt;
&lt;p&gt;Syncing happens via a shell script, &lt;a href=&quot;https://github.com/banga/dotfiles-template/blob/master/.updatelaptop&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;.updatelaptop&lt;/a&gt;, which is invoked automatically every time you start a new shell. Once a day, it will pull any updates from the repo and trigger the &lt;a href=&quot;https://github.com/banga/dotfiles-template/blob/master/update.py&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;update.py&lt;/a&gt; file which ensures that the environment matches the expected state.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/banga/dotfiles-template/blob/master/update.py&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;update.py&lt;/a&gt; script runs a number of checks and runs fixes for checks that fail. Here are the notable ones:&lt;/p&gt;
&lt;h3&gt;Dotfiles&lt;/h3&gt;
&lt;p&gt;This ensures that the dotfiles in my home directory are symlinked to the dotfiles checked into this repo. I keep my common shell settings in &lt;code class=&quot;&quot;&gt;.shrc&lt;/code&gt; and machine-specific settings in &lt;code class=&quot;&quot;&gt;.hyperlocal.shrc&lt;/code&gt;, which is gitignored.&lt;/p&gt;
&lt;h3&gt;Brew&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;&quot;&gt;BrewBundle&lt;/code&gt; ensures that everything in the checked-in &lt;code class=&quot;&quot;&gt;Brewfile&lt;/code&gt; is installed. This is the most powerful check for ensuring a consistent environment across machines. I can even use it to sync my favorite monospace font: &lt;a href=&quot;https://www.jetbrains.com/lp/mono/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;JetBrains mono&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Zsh&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;&quot;&gt;OhMyZsh&lt;/code&gt; and &lt;code class=&quot;&quot;&gt;OhMyZshCustomPlugins&lt;/code&gt; checks ensure that &lt;a href=&quot;https://ohmyz.sh/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Oh My Zsh&lt;/a&gt; and the plugins I use for it are installed. The plugins are included as submodules in this repo and symlinked to the zsh directory.&lt;/p&gt;
&lt;h3&gt;Git commit previews&lt;/h3&gt;
&lt;p&gt;This copies a custom CSS file I wrote to make &lt;code class=&quot;&quot;&gt;git instaweb&lt;/code&gt; output look similar to Github. Along with this file, I have a shell command that allows me to preview my latest commit before pushing:&lt;/p&gt;
&lt;pre&gt;&lt;pre class=&quot;shiki shiki-themes vitesse-light github-dark&quot; style=&quot;--shiki-light:#393a34;--shiki-dark:#e1e4e8;--shiki-light-bg:#ffffff;--shiki-dark-bg:#24292e&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;--shiki-light:#59873A;--shiki-dark:#B392F0&quot;&gt; gcpr&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#59873A;--shiki-dark:#B392F0&quot;&gt;    pkill&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A65E2B;--shiki-dark:#79B8FF&quot;&gt; -9&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt; lighttpd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#59873A;--shiki-dark:#B392F0&quot;&gt;    git&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt; instaweb&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt; start&lt;/span&gt;&lt;span style=&quot;--shiki-light:#A65E2B;--shiki-dark:#79B8FF&quot;&gt; -l&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B07D48;--shiki-dark:#E1E4E8&quot;&gt;    commit&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#9ECBFF&quot;&gt;$(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#59873A;--shiki-dark:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt; rev-parse &lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#79B8FF&quot;&gt;${1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AB5959;--shiki-dark:#F97583&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;HEAD&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#9ECBFF&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#A0ADA0;--shiki-dark:#6A737D&quot;&gt;    # Assumes git instaweb is running on port 1234&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#59873A;--shiki-dark:#B392F0&quot;&gt;    open&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;http://127.0.0.1:1234/?p=.git;a=commitdiff;ds=sidebyside;h=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#E1E4E8&quot;&gt;$commit&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://shreyb.dev/assets/git-commit-preview.gif&quot; loading=&quot;lazy&quot; alt=&quot;Gif showing git commit preview command working&quot;/&gt;&lt;/p&gt;
&lt;h3&gt;VS Code&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;&quot;&gt;VSCodeSyncing&lt;/code&gt; and &lt;code class=&quot;&quot;&gt;VSCodeExtensions&lt;/code&gt; checks ensure that my vscode settings and extensions are synced across machines. I find this particularly useful because I often make small tweaks to vscode in one machine and end up needing them on another.&lt;/p&gt;
&lt;h2&gt;Dropbox&lt;/h2&gt;
&lt;p&gt;I still end up using Dropbox for syncing some settings which I change often enough for it to be too annoying to have to check-in into a repo and push. These include &lt;a href=&quot;https://shreyb.dev/blog/2020/03/02/little-known-features-of-iterm2.html&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;iTerm2 settings&lt;/a&gt;, Karabiner configurations, Alfred settings etc.&lt;/p&gt;</content>
    </entry>
<entry>
      <title>Little known features of iTerm2</title>
      <link href="https://shreyb.dev/blog/2020/03/02/little-known-features-of-iterm2.html" />
      <updated>2020-03-02T00:00:00.000Z</updated>
      <id>https://shreyb.dev/blog/2020/03/02/little-known-features-of-iterm2.html</id>
      <author>
        <name>Shrey Banga</name>
      </author>
      <content type="html">&lt;h1&gt;Little known features of iTerm2&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://iterm2.com/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;iTerm2&lt;/a&gt; has a lot of little-known features that can make development much easier.&lt;/p&gt;
&lt;h2&gt;Smart Selection&lt;/h2&gt;
&lt;p&gt;If you work in a large codebase, chances are you often need to open commits on Github, or revisions in Phabricator or tickets in your in-house bug tracker. This usually involves copying and pasting an identifier into a URL and opening that in your browser. For example, you may want to open commit hashes or PRs on Github with a single click. You can make iTerm2 recognize arbitrary ids and take custom actions using them when they are Command-clicked via &lt;a href=&quot;https://www.iterm2.com/documentation-smart-selection.html&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Smart Selections&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here are a couple of examples:&lt;/p&gt;
&lt;h3&gt;Open commits on Github&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://shreyb.dev/assets/iTerm2-smart-selection-github.gif&quot; loading=&quot;lazy&quot; alt=&quot;Gif showing smart selection opening a commit on Github&quot;/&gt;&lt;/p&gt;
&lt;p&gt;To make Command-clicking on a commit hash open it in Github, do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href=&quot;https://github.com/github/hub&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In your iTerm2 Preferences, go to &lt;code class=&quot;&quot;&gt;Profiles -&amp;gt; Advanced -&amp;gt; Smart Selection -&amp;gt; Edit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click the &lt;code class=&quot;&quot;&gt;+&lt;/code&gt; button to add a new rule and set the &lt;code class=&quot;&quot;&gt;Regular Expression&lt;/code&gt; to &lt;code class=&quot;&quot;&gt;[0-9a-f]{7,40}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click on &lt;code class=&quot;&quot;&gt;Edit Actions...&lt;/code&gt; and add a new action&lt;/li&gt;
&lt;li&gt;Set the &lt;code class=&quot;&quot;&gt;Action&lt;/code&gt; to &lt;code class=&quot;&quot;&gt;Run Command...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the &lt;code class=&quot;&quot;&gt;Parameter&lt;/code&gt; to &lt;code class=&quot;&quot;&gt;cd &amp;quot;\d&amp;quot; &amp;amp;&amp;amp; /usr/local/bin/hub browse -- commit/\0&lt;/code&gt;. You may have to update the path to &lt;code class=&quot;&quot;&gt;hub&lt;/code&gt; here if you installed it to a different directory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once this is done, &lt;code class=&quot;&quot;&gt;Command-click&lt;/code&gt; on a commit hash in iTerm2 should open it in its respective repository if it exists on Github. You can customize this technique to open PRs and Issues on Github as well.&lt;/p&gt;
&lt;h3&gt;Open revisions in Phabricator&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In your iTerm2 Preferences, go to &lt;code class=&quot;&quot;&gt;Profiles -&amp;gt; Advanced -&amp;gt; Smart Selection -&amp;gt; Edit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click the &lt;code class=&quot;&quot;&gt;+&lt;/code&gt; button to add a new rule and set the &lt;code class=&quot;&quot;&gt;Regular Expression&lt;/code&gt; to &lt;code class=&quot;&quot;&gt;D[:number:]{5}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click on &lt;code class=&quot;&quot;&gt;Edit Actions...&lt;/code&gt; and add a new action&lt;/li&gt;
&lt;li&gt;Set the &lt;code class=&quot;&quot;&gt;Action&lt;/code&gt; to &lt;code class=&quot;&quot;&gt;Open URL...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the &lt;code class=&quot;&quot;&gt;Parameter&lt;/code&gt; to &lt;code class=&quot;&quot;&gt;https://secure.phabricator.com/\0&lt;/code&gt; or a similar URL for your organization.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Dynamic Profiles&lt;/h2&gt;
&lt;p&gt;If you work on a project that requires starting a number of terminal sessions in specific conditions, it can get annoying to get your environment running from scratch. iTerm2&amp;#x27;s &lt;a href=&quot;https://www.iterm2.com/documentation-dynamic-profiles.html&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;Dynamic Profiles&lt;/a&gt; allow you to create custom profiles that can depend on other profiles. You can use this to create a hierarchy of profiles that share your common settings but run different commands on startup.&lt;/p&gt;
&lt;p&gt;For example, say your project always needs you to be running &lt;code class=&quot;&quot;&gt;npm run build&lt;/code&gt;, &lt;code class=&quot;&quot;&gt;npm run server&lt;/code&gt; and &lt;code class=&quot;&quot;&gt;npm run worker&lt;/code&gt; during development. You can use dynamic profiles to start iTerm2 with all of these commands running as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate four GUIDs by running &lt;code class=&quot;&quot;&gt;uuidgen&lt;/code&gt; in your terminal four times and copying the results.&lt;/li&gt;
&lt;li&gt;Create a file in &lt;code class=&quot;&quot;&gt;~/Library/Application Support/iTerm2/DynamicProfiles&lt;/code&gt; with these contents (fill in the parts in &lt;code class=&quot;&quot;&gt;&amp;lt;...&amp;gt;&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;pre class=&quot;shiki shiki-themes vitesse-light github-dark&quot; style=&quot;--shiki-light:#393a34;--shiki-dark:#e1e4e8;--shiki-light-bg:#ffffff;--shiki-dark-bg:#24292e&quot; tabindex=&quot;0&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Profiles&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Development&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Guid&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;&amp;lt;guid1&amp;gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Dynamic Profile Parent Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Default&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Working Directory&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;&amp;lt;path-to-your-project&amp;gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Custom Directory&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Yes&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Build&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Guid&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;&amp;lt;guid2&amp;gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Dynamic Profile Parent Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Development&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Initial Text&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;npm run build&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Guid&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;&amp;lt;guid3&amp;gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Dynamic Profile Parent Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Development&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Initial Text&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;npm run server&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Worker&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Guid&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;&amp;lt;guid4&amp;gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Dynamic Profile Parent Name&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;Development&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;      &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#998418;--shiki-dark:#79B8FF&quot;&gt;Initial Text&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#79B8FF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B56959;--shiki-dark:#9ECBFF&quot;&gt;npm run worker&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B5695999;--shiki-dark:#9ECBFF&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#999999;--shiki-dark:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Reload iTerm2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These profiles should now show up in iTerm2 as dynamic profiles. You can then start sessions with these profiles to create a window arrangement and hit &lt;code class=&quot;&quot;&gt;Command-Shift-S&lt;/code&gt; to save it. Then you can start all of these sessions at any time by just pressing &lt;code class=&quot;&quot;&gt;Command-Shift-R&lt;/code&gt; or tell iTerm2 to open the arrangement when it starts! Check out &lt;a href=&quot;https://blog.andrewray.me/how-to-create-custom-iterm2-window-arrangments/&quot; node=&quot;[object Object]&quot; target=&quot;_blank&quot;&gt;https://blog.andrewray.me/how-to-create-custom-iterm2-window-arrangments/&lt;/a&gt; for a detailed guide on window arrangements.&lt;/p&gt;</content>
    </entry>
</feed>