<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dawid</title>
    <description>The latest articles on Forem by Dawid (@dawidcodes).</description>
    <link>https://forem.com/dawidcodes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1226704%2Fc085ecec-40e1-4719-9556-484fd03e7edc.jpg</url>
      <title>Forem: Dawid</title>
      <link>https://forem.com/dawidcodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dawidcodes"/>
    <language>en</language>
    <item>
      <title>How to use a custom font on Excalidraw.com</title>
      <dc:creator>Dawid</dc:creator>
      <pubDate>Thu, 06 Jun 2024 18:44:52 +0000</pubDate>
      <link>https://forem.com/dawidcodes/how-to-use-a-custom-font-on-excalidrawcom-4jl4</link>
      <guid>https://forem.com/dawidcodes/how-to-use-a-custom-font-on-excalidrawcom-4jl4</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Excalidraw is a great whiteboarding tool, useful for technical diagrams and wireframes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;The default handwritten font looks quite unprofessional and can be difficult to read&lt;/p&gt;

&lt;p&gt;Additionally, there is no official way to add custom fonts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;The solution is to run a custom script on every page load to override the default fonts.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Download the "scripty" chrome extension
&lt;/h4&gt;

&lt;p&gt;You can download the extension &lt;a href="https://chromewebstore.google.com/detail/scripty-javascript-inject/milkbiaeapddfnpenedfgbfdacpbcbam?hl=en"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will allow you to inject custom js on specific web pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Configure automatic script injection
&lt;/h4&gt;

&lt;p&gt;Once you have scripty installed, create a new script and configure it to run automatically when the URL contains &lt;a href="https://app.excalidraw.com/"&gt;https://app.excalidraw.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fct8nsf55fbyjwhhpipke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fct8nsf55fbyjwhhpipke.png" alt="Configure automatic script ui" width="774" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Add custom font script
&lt;/h4&gt;

&lt;p&gt;Write a script to override one of the Excalidraw default fonts with your chosen font&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Custom font script started&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Add the font-face definition&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
  @font-face {
    font-family: 'Helvetica';
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/shantellsans/v9/FeVhS0pCoLIo-lcdY7kjvNoQg2xkycTqsuA6bi9pTt8YiT-NXidjb_ee-maigL6R8nKVh8BbE1mv4wwMMm1lebY.woff2) format('woff2');
  }
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Custom font added&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing, the default fonts are:&lt;/p&gt;

&lt;p&gt;Handdrawn = 'Virgil'&lt;br&gt;
Normal = 'Helvetica'&lt;br&gt;
Code = 'source-code-pro'&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Bonus tip: using google fonts
&lt;/h4&gt;

&lt;p&gt;Find your font in google fonts, click on embed code, and under the web tab select the @import option&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkfgo44f53b0nz9xtaz2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkfgo44f53b0nz9xtaz2.png" alt="google fonts ui" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem here is that google fonts default import url will set the font name to be the real name of the font.&lt;/p&gt;

&lt;p&gt;We want to manually alter the name of the font to override the fonts in excalidraw.&lt;/p&gt;

&lt;p&gt;To achieve this, you can navigate to the font url in the browser eg visit &lt;a href="https://fonts.googleapis.com/css2?family=Shantell+Sans:ital,wght@0,300..800;1,300..800&amp;amp;display=swap"&gt;https://fonts.googleapis.com/css2?family=Shantell+Sans:ital,wght@0,300..800;1,300..800&amp;amp;display=swap&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;From here you can copy the entire css, paste it into vs code, and use find/replace to change all the font names .&lt;/p&gt;

&lt;p&gt;For example, to replace the default handdrawn font (Virgil) with a custom handdrawn font (Shantell Sans), you can use the link above, copy all the CSS and change the name from 'Shantell Sans' to 'Virgil' to trick Excalidraw into replacing the fonts.&lt;/p&gt;

&lt;p&gt;Now add this code into the script provided above and youre ready to go.&lt;/p&gt;

&lt;p&gt;Here is the script for a fully working example &lt;a href="https://pastebin.com/raw/1LULgXuX"&gt;https://pastebin.com/raw/1LULgXuX&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This article provides you with everything you need to implement a custom font in Excalidraw.&lt;/p&gt;

&lt;p&gt;I hope that someone finds this useful&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>css</category>
    </item>
    <item>
      <title>Simplifying Complex Type Display in TypeScript and VS Code</title>
      <dc:creator>Dawid</dc:creator>
      <pubDate>Fri, 24 May 2024 10:40:05 +0000</pubDate>
      <link>https://forem.com/dawidcodes/simplifying-complex-type-display-in-typescript-and-vs-code-4f1</link>
      <guid>https://forem.com/dawidcodes/simplifying-complex-type-display-in-typescript-and-vs-code-4f1</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;Complex typescript types can result in a huge confusing mess when hovering on a variable.&lt;/p&gt;

&lt;p&gt;This can make it hard to quickly understand the type information.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore techniques that can help simplify the display of complex types in VS Code using TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem:
&lt;/h3&gt;

&lt;p&gt;Consider the following example where we have a &lt;code&gt;State&amp;lt;T&amp;gt;&lt;/code&gt; type and a &lt;code&gt;createState&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TStateValue&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;StateValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
        &lt;span class="nx"&gt;TSelector&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TStateValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TStateValue&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;TStateValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;TSelector&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;TSelector&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TStateValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;TReturnType&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;TReturnType&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TStateValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;StateValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the &lt;code&gt;createState&lt;/code&gt; function to create a store with a specific type, like &lt;code&gt;createState(0)&lt;/code&gt;, VS Code expands the type and displays a verbose and complex type definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/*
numberStore: {
  get: &amp;lt;TSelector extends (state: number) =&amp;gt; unknown = (state: number) =&amp;gt; number&amp;gt;(selector?: TSelector | undefined) =&amp;gt; TSelector extends (state: number) =&amp;gt; infer TReturnType ? TReturnType : number;
  set: (newValueOrFn: number | ((prev: number) =&amp;gt; number)) =&amp;gt; void;
  use: &amp;lt;TSelector extends (state: number) =&amp;gt; unknown = (state: number) =&amp;gt; number&amp;gt;(selector?: TSelector | undefined, equalityFn?: EqualityChecker&amp;lt;...&amp;gt; | undefined) =&amp;gt; TSelector extends (state: number) =&amp;gt; infer TReturnType ? TReturnType : number;
  onChange: (callback: (value: number, prevValue: number) =&amp;gt; void, options?: OnChangeOptions&amp;lt;...&amp;gt; | undefined) =&amp;gt; UnsubscribeFn;
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution: making the type more Opaque
&lt;/h3&gt;

&lt;p&gt;To simplify the display of complex types in VS Code, we can leverage TypeScript's intersection types and a clever type definition. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a &lt;code&gt;Simplify&lt;/code&gt; utility type:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Simplify&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This type expands objects to show all the key/value types. Given an empty object, it will resolve to an empty object.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Intersect your complex type with &lt;code&gt;Simplify&amp;lt;{}&amp;gt;&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TStateValue&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;StateValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Simplify&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By intersecting the &lt;code&gt;State&amp;lt;T&amp;gt;&lt;/code&gt; type with &lt;code&gt;Simplify&amp;lt;{}&amp;gt;&lt;/code&gt;, we trigger a mechanism in VS Code that simplifies the displayed type when hovering over variables or types, without altering the actual type.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the modified type in the &lt;code&gt;createState&lt;/code&gt; function:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;StateValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Hovering over `numberStore` will display `State&amp;lt;number&amp;gt;` instead of the expanded type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the &lt;code&gt;createState&lt;/code&gt; function with the modified &lt;code&gt;State&amp;lt;T&amp;gt;&lt;/code&gt; type, VS Code will display the simplified type name &lt;code&gt;State&amp;lt;number&amp;gt;&lt;/code&gt; instead of the verbose type definition when hovering over &lt;code&gt;numberStore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note: from my experiments, using &lt;code&gt;type NumberStore = State&amp;lt;number&amp;gt;&lt;/code&gt; does not achieve the same result. It seems to only work when the type is a return of a function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Achieving the Reverse effect: expanding the type
&lt;/h3&gt;

&lt;p&gt;Sometimes you may want to expand the whole type to show all the values on hover, instead of showing the &lt;code&gt;Type&amp;lt;Generic&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Simplify&lt;/code&gt; generic type can help you achieve this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SomeBuilderType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SomeSuperComplexParsingFunction&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// when you hover on the input, it's to know what the input type is&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ExpandedInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Simplify&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// ExpandedInput = { id: number } &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion:
&lt;/h3&gt;

&lt;p&gt;The workaround presented in this article can help simplify the display of complex types in VS Code when working with TypeScript. &lt;/p&gt;

&lt;p&gt;I hope this article helps you navigate and simplify the display of complex types in your TypeScript projects using VS Code. Happy coding!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>types</category>
      <category>generics</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>How to Make your Web App Super-Satisfying in less than 5 minutes with Davstack Sound</title>
      <dc:creator>Dawid</dc:creator>
      <pubDate>Sun, 07 Apr 2024 23:30:40 +0000</pubDate>
      <link>https://forem.com/dawidcodes/make-your-web-app-stand-out-in-less-than-5-minutes-with-davstack-sound-3ea</link>
      <guid>https://forem.com/dawidcodes/make-your-web-app-stand-out-in-less-than-5-minutes-with-davstack-sound-3ea</guid>
      <description>&lt;h2&gt;
  
  
  Why sound?
&lt;/h2&gt;

&lt;p&gt;Game devs have know this for years - our reward systems love the &lt;strong&gt;satisfying feeling&lt;/strong&gt; of hearing ticks and clicks when we engage with the environment, and celebrations when we make progress.&lt;/p&gt;

&lt;p&gt;Even though effect of sounds is often subconscious, the impact of high quality &lt;em&gt;micro-interactions&lt;/em&gt; should not be underestimated.&lt;/p&gt;

&lt;p&gt;However, with a million other things to do, it can be hard to find the &lt;em&gt;time and effort&lt;/em&gt; to implement sounds effects and sound settings into your web apps.&lt;/p&gt;

&lt;p&gt;For this reason, I made a small but mighty react makes the process of adding sounds to your React/Next.js a &lt;strong&gt;joy to work with&lt;/strong&gt; - both in terms of developer experience (DX) and user experience (UX).&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage demo
&lt;/h2&gt;

&lt;p&gt;After a quick 2-minute setup, you will have access to a wide range of high quality sound effects that you can call anywhere in your app with 1 line of code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/sound-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
            &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;switchOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Click me
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick Start Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 0: What is Davstack sound?
&lt;/h3&gt;

&lt;p&gt;Davstack Sound is super fast and simple typescript sound management library for React/Next.js apps.&lt;/p&gt;

&lt;p&gt;It is built on top of Howler.js, a battle-tested audio library that supports all major browsers.&lt;/p&gt;

&lt;p&gt;It also makes global sound settings a breeze, allowing users to change volume, mute, or stop all sounds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Installing Davstack Sound
&lt;/h3&gt;

&lt;p&gt;To get started, install Davstack Sound in your project by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @davstack/sound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Adding Sound Assets
&lt;/h3&gt;

&lt;p&gt;Davstack sound is completely sound-agnostic - feel free to use whatever sounds right to you and your users.&lt;/p&gt;

&lt;p&gt;Simply place all your sound assets into your &lt;code&gt;/public&lt;/code&gt; folder (assuming Next.js usage, adjust otherwise)&lt;/p&gt;

&lt;p&gt;I recommend using the Material Design Sound Assets. These assets provide a wide range of well-crafted sounds that are well suited for application interactions.&lt;/p&gt;

&lt;h4&gt;
  
  
  If you want to use the Material Design Sound Assets, follow these steps:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download the Material Design Sound Assets from the official website: &lt;a href="https://m2.material.io/design/sound/sound-resources.html"&gt;Material Design Sound Resources&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract the downloaded ZIP file and locate the 4 main sound folders. (&lt;code&gt;.ogg&lt;/code&gt; file format is recommended for a balance between quality and file size)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rename the folders to: alert, navigation, hero, secondary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the renamed folders into the &lt;code&gt;/public/sounds/material&lt;/code&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Defining Your Sound Store
&lt;/h3&gt;

&lt;p&gt;With the sound assets in place, it's time to define your sound store. Create a new file called &lt;code&gt;sound-store.ts&lt;/code&gt; in your project's &lt;code&gt;lib&lt;/code&gt; directory (or any other appropriate location).&lt;/p&gt;

&lt;h4&gt;
  
  
  Sound Store definition example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/sound-store.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSoundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@davstack/sound&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// path relative to /public (assuming you are using next.js) eg `./public/sounds/switch-on.mp3`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SOUND_BASE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sounds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSoundStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;soundNameToPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;switchOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/switch-on.mp3`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;switchOff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/switch-off.mp3`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  To import all material sounds, copy the following example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/sound-store.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSoundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@davstack/sound&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sounds/material&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// points to /public/sounds/material&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;materialSoundNamesToPaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// can also add any other custom sounds here&lt;/span&gt;
    &lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;highIntensity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/alert_high-intensity.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;simple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/alert_simple.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;gentleAlarm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/alarm_gentle.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ringtoneMinimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/ringtone_minimal.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;error1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/alert_error-01.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;error2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/alert_error-02.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;error3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/alert_error-03.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;decorative1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/notification_decorative-01.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;decorative2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/notification_decorative-02.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;highIntensity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/notification_high-intensity.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;simple1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/notification_simple-01.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;simple2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/alert/notification_simple-02.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;navigation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;backwardSelection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/navigation_backward-selection.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;forwardSelection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/navigation_forward-selection.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hoverTap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/navigation_hover-tap.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;backwardSelectionMinimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/navigation_backward-selection-minimal.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;forwardSelectionMinimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/navigation_forward-selection-minimal.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;selectionCompleteCelebration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/navigation_selection-complete-celebration.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;transitionLeft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/navigation_transition-left.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;transitionRight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/navigation_transition-right.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;unavailableSelection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/navigation_unavailable-selection.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/navigation-cancel.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;stateChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;confirmDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/state-change_confirm-down.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;confirmUp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/state-change_confirm-up.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;decorativeCelebration1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/hero/hero_decorative-celebration-01.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;decorativeCelebration2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/hero/hero_decorative-celebration-02.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;decorativeCelebration3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/hero/hero_decorative-celebration-03.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;simpleCelebration1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/hero/hero_simple-celebration-01.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;simpleCelebration2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/hero/hero_simple-celebration-02.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;simpleCelebration3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/hero/hero_simple-celebration-03.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;cameraShutter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_camera-shutter.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_lock.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_unlock.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;tapVariant1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_tap-variant-01.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tapVariant2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_tap-variant-02.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tapVariant3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_tap-variant-03.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tapVariant4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/primary/ui_tap-variant-04.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/ui_loading.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;refreshFeed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MATERIAL_SOUND_BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/secondary/ui_refresh-feed.ogg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSoundStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;soundNameToPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;materialSoundNamesToPaths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: you may want to comment out the sounds you are not using to avoid unnecessary loading of sound assets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Playing Sounds
&lt;/h3&gt;

&lt;p&gt;With the sound store set up, playing sounds in your app is a breeze. Simply import the &lt;code&gt;soundStore&lt;/code&gt; and call the &lt;code&gt;playSound&lt;/code&gt; method with the desired sound name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lib/sound-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hero.decorativeCelebration1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we import the &lt;code&gt;soundStore&lt;/code&gt; and play the "hero.decorativeCelebration1" sound using the flattened object notation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Initializing Sounds (Optional)
&lt;/h3&gt;

&lt;p&gt;To ensure that sounds play instantly without any delay, you can initialize the sounds when your app loads. This step is optional but recommended for the best user experience.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/sound-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InitAllSounds&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Place the &lt;code&gt;soundStore.InitAllSounds&lt;/code&gt; component in your app's root layout component. This will preload and cache all the sounds, ensuring instant playback when needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Customizing Sound Settings
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Adjusting global/individual sound settings
&lt;/h4&gt;

&lt;p&gt;Davstack makes it easy to define global sound settings, such as adjusting volume or enabling/disabling sounds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Adjusting settings when playing a sound&lt;/span&gt;
&lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;playbackRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Adjusting global settings&lt;/span&gt;
&lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;soundEnabled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Giving users control over global volume
&lt;/h4&gt;

&lt;p&gt;It is best practice to provide users with control over sound settings in your app.&lt;/p&gt;

&lt;p&gt;To give users control over the global volume, you can create a volume control component that interacts with the &lt;code&gt;soundStore&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/volume-control.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/sound-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VolumeControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Volume control"&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt;
            &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
            &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
            &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0.01"&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onMouseUp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onTouchEnd&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a range input that represents the volume control. It retrieves the current volume value from the &lt;code&gt;soundStore&lt;/code&gt; using the &lt;code&gt;use&lt;/code&gt; method and updates the volume when the input value changes. &lt;/p&gt;

&lt;p&gt;We also play a 'pop' sound when the user releases the mouse or ends a touch interaction to provide auditory feedback.&lt;/p&gt;

&lt;p&gt;Note: if the global sound is set to 0.5 and you pass in a volume of 0.5 to the playSound function, the sound will play at 0.25 volume (0.5 * 0.5)&lt;/p&gt;

&lt;h4&gt;
  
  
  Allowing users to enable/disable sounds globally
&lt;/h4&gt;

&lt;p&gt;To allow users to enable or disable sounds globally, you can create a sound toggle component that interacts with the &lt;code&gt;soundStore&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/sound-toggle.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/sound-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SoundToggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;soundEnabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;soundEnabled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
            &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;soundEnabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;switchOff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;soundEnabled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;soundEnabled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="nx"&gt;soundStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playSound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;switchOn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;soundEnabled&lt;/span&gt;
                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sound On (press to turn off)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sound Off (press to turn on)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a button that toggles the sound on or off. It retrieves the current &lt;code&gt;soundEnabled&lt;/code&gt; value from the &lt;code&gt;soundStore&lt;/code&gt; using the &lt;code&gt;use&lt;/code&gt; method and updates the value when the button is clicked. We also play different sounds ('switchOff' and 'switchOn') depending on the state change to provide auditory feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;While adding sounds to your web app may seem like a subtle change, it can make for a surprisingly satisfying user experience.&lt;/p&gt;

&lt;p&gt;With Davstack Sound, the process of integrating sounds into your React/Next.js app becomes a delightful and effortless experience.&lt;/p&gt;

&lt;p&gt;If you found this guide / package helpful then check out the other &lt;a href="https://davstack.com/"&gt;Davstack&lt;/a&gt; packages for more tools to enhance your web development workflow.&lt;/p&gt;

&lt;p&gt;Have a great day, and happy coding! 📈&lt;/p&gt;

&lt;p&gt;PS Please share a link to any other audio-asset resources or your website on the comments, I'd love to see your creations!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>ux</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Boost Your Productivity: Essential Git Aliases to Save 20 Minutes Daily</title>
      <dc:creator>Dawid</dc:creator>
      <pubDate>Tue, 05 Dec 2023 15:35:22 +0000</pubDate>
      <link>https://forem.com/dawidcodes/boost-your-productivity-essential-git-aliases-to-save-20-minutes-daily-bee</link>
      <guid>https://forem.com/dawidcodes/boost-your-productivity-essential-git-aliases-to-save-20-minutes-daily-bee</guid>
      <description>&lt;p&gt;(note: surprisingly, this article was not written by Ai)&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;Git aliases are a powerful method of automating tasks - saving you time and making coding more enjoyable.&lt;/p&gt;

&lt;p&gt;This blog post will give you everything you need to know to get started with optimizing your workflow.&lt;/p&gt;

&lt;p&gt;Keep reading to get access to my custom code snippets that are will definitely save you many precious dev minutes and guarantee a job at google (100% guaranteed, no doubt)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Up Prerequisites (2 mins)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before diving into the aliases, here are a few prerequisites &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure you have Git Bash installed. for more info see &lt;a href="https://git-scm.com/downloads"&gt;the official download page&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ensure you have the &lt;code&gt;code&lt;/code&gt; command configured (See below)&lt;/li&gt;
&lt;li&gt;(optional) I recommend to set up git bash as default vs code terminal, for more info see &lt;a href="https://medium.com/danielpadua/git-bash-with-vscode-593d5998f6be"&gt;setting up git bash with vs code&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting up the &lt;code&gt;code&lt;/code&gt; command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;code&lt;/code&gt; command creates a new file AND opens it in your code editor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ~/your-project-directory/src&amp;gt; code my-file-name.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: unlike &lt;code&gt;touch&lt;/code&gt; , when the new file is open in your code editor you must hit &lt;code&gt;ctrl+s&lt;/code&gt; to ensure is saved.&lt;/p&gt;

&lt;p&gt;The convenience this provides is why it is beloved by many developers and a consistent part of my daily development workflow.&lt;/p&gt;

&lt;p&gt;The code command is required for some of the advanced bash scripts later in this article to work.&lt;/p&gt;

&lt;p&gt;Here is how to set it up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside vs-code, press F1 to open the command pallete&lt;/li&gt;
&lt;li&gt;type &lt;code&gt;shell command&lt;/code&gt; to find &lt;code&gt;Shell Command: Install 'code' command in PATH command&lt;/code&gt; and hit enter&lt;/li&gt;
&lt;li&gt;restart your terminal&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more info on this, see &lt;a href="https://stackoverflow.com/questions/46638944/code-is-not-recognized-as-an-internal-or-external-command"&gt;this stack overflow post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Defining Git Bash Aliases&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  My approach
&lt;/h3&gt;

&lt;p&gt;These scripts have been written with typescript / python developers in mind.&lt;/p&gt;

&lt;p&gt;My aim is to create scripts that are easy to understand and change by developers most familiar with high-level programming languages.&lt;/p&gt;

&lt;p&gt;While some members of the Bash scripting community may find my snippets somewhat unconventional, I hope that the majority finds my methods to helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining aliases overview:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.bashrc&lt;/code&gt; is where you will be placing all of your alias definitions.&lt;/li&gt;
&lt;li&gt;You can access this using &lt;code&gt;code ~/.bashrc&lt;/code&gt;  (or the rc alias later on)&lt;/li&gt;
&lt;li&gt;After making changes, ensure to save &lt;code&gt;.bashrc&lt;/code&gt; restart your terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;ctrl+'&lt;/code&gt; to open terminal in vs code&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;ctrl+shift+5&lt;/code&gt; to add a new terminal

&lt;ul&gt;
&lt;li&gt;eg if you have your development sever running in one terminal, you can still use the second terminal to write commands&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;ctrl+d&lt;/code&gt; to close the specific terminal instance that you are focused on&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;ctrl+c&lt;/code&gt; to cancel operation&lt;/li&gt;
&lt;li&gt;can “restart” the terminal by using &lt;code&gt;ctrl+shift+5&lt;/code&gt; to create a new one and then &lt;code&gt;ctrl+d&lt;/code&gt; to close the current one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic use cases
&lt;/h2&gt;

&lt;p&gt;These basic use cases are mostly for convenience and DX&lt;/p&gt;

&lt;h3&gt;
  
  
  The alias for aliases!
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# Overview: &lt;/span&gt;
  &lt;span class="c"&gt;#   Opens ~/.bashrc in vscode so that you can edit your aliases&lt;/span&gt;
  &lt;span class="c"&gt;# Usage:&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/anywhere&amp;gt; rc&lt;/span&gt;
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;rc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"code ~/.bashrc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Relative navigation aliases
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# Overview:&lt;/span&gt;
  &lt;span class="c"&gt;#   Aliases for easily navigating relative to the current directory&lt;/span&gt;
  &lt;span class="c"&gt;# Usage:&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app/src/folder/nested-folder&amp;gt; ...&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app/src&amp;gt; &lt;/span&gt;
  &lt;span class="nb"&gt;alias&lt;/span&gt; .&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd .'&lt;/span&gt;            &lt;span class="c"&gt;# navigate to current directory&lt;/span&gt;
  &lt;span class="nb"&gt;alias&lt;/span&gt; ..&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ..'&lt;/span&gt;          &lt;span class="c"&gt;# navigate to parent directory&lt;/span&gt;
  &lt;span class="nb"&gt;alias&lt;/span&gt; ...&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ../../'&lt;/span&gt;     &lt;span class="c"&gt;# navigate to grandparent directory&lt;/span&gt;
  &lt;span class="nb"&gt;alias&lt;/span&gt; ....&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd ../../../'&lt;/span&gt; &lt;span class="c"&gt;# navigate to great-grandparent directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Package manager
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# Overview: &lt;/span&gt;
  &lt;span class="c"&gt;#   Runs pnpm as normal but more concise&lt;/span&gt;
  &lt;span class="c"&gt;#   Replace with yarn or npm if needed&lt;/span&gt;
  &lt;span class="c"&gt;# Usage:&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; x dev &lt;/span&gt;
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'pnpm "$@"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced custom use cases
&lt;/h2&gt;

&lt;p&gt;These are custom use cases that save me a lot of time and effort everyday, and I highly recommend trying them out!&lt;/p&gt;

&lt;h3&gt;
  
  
  Absolute Navigation (relative to the root of the repo)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# This a helper function for the git aliases below&lt;/span&gt;

  &lt;span class="c"&gt;# credit: https://stackoverflow.com/a/38852055&lt;/span&gt;
  &lt;span class="c"&gt;# Print the name of the git working tree's root directory&lt;/span&gt;
  &lt;span class="k"&gt;function &lt;/span&gt;git_root&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;root first_commit
    &lt;span class="c"&gt;# git displays its own error if not in a repository&lt;/span&gt;
    &lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--show-toplevel&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return
    if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nv"&gt;$root&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$root&lt;/span&gt;
      &lt;span class="k"&gt;return
    elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--is-inside-git-dir&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="c"&gt;# We're inside the .git directory&lt;/span&gt;
      &lt;span class="c"&gt;# Store the commit id of the first commit to compare later&lt;/span&gt;
      &lt;span class="c"&gt;# It's possible that $GIT_DIR points somewhere not inside the repo&lt;/span&gt;
      &lt;span class="nv"&gt;first_commit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-list &lt;span class="nt"&gt;--parents&lt;/span&gt; HEAD | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;: Can't get initial commit"&lt;/span&gt; 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return
      &lt;/span&gt;&lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--git-dir&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/.. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="c"&gt;# subshell so we don't change the user's working directory&lt;/span&gt;
      &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;git rev-list &lt;span class="nt"&gt;--parents&lt;/span&gt; HEAD | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$first_commit&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;&lt;span class="nb"&gt;pwd
        &lt;/span&gt;&lt;span class="k"&gt;else
          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FUNCNAME&lt;/span&gt;&lt;span class="s2"&gt;: git directory is not inside its repository"&lt;/span&gt; 2&amp;gt;&amp;amp;1
          &lt;span class="nb"&gt;false
        &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
      &lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FUNCNAME&lt;/span&gt;&lt;span class="s2"&gt;: Can't determine repository root"&lt;/span&gt; 2&amp;gt;&amp;amp;1
      &lt;span class="nb"&gt;false
    &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;# Overview:&lt;/span&gt;
  &lt;span class="c"&gt;#   Custom implementation of cd command that uses absolute path from git root&lt;/span&gt;
  &lt;span class="c"&gt;#   Supports custom aliases eg: r a = cd to apps&lt;/span&gt;
  &lt;span class="c"&gt;#   The alises configured below are specialised for monorepo development with turbo.build &lt;/span&gt;
  &lt;span class="c"&gt;#   You can easily tailor these to your needs eg for a non-monorepo setup &lt;/span&gt;
  &lt;span class="c"&gt;# Usage examples:&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; r a &lt;/span&gt;
  &lt;span class="c"&gt;#   =&amp;gt; ~/dev/my-app/apps&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; r a/w&lt;/span&gt;
  &lt;span class="c"&gt;#   =&amp;gt; ~/dev/my-app/apps/webapp&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; r a/d&lt;/span&gt;
  &lt;span class="c"&gt;#   =&amp;gt; ~/dev/my-app/apps/docs&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; r p &lt;/span&gt;
  &lt;span class="c"&gt;#   =&amp;gt; ~/dev/my-app/packages&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; r p/ui&lt;/span&gt;
  &lt;span class="c"&gt;#   =&amp;gt; ~/dev/my-app/packages/ui&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; r t&lt;/span&gt;
  &lt;span class="c"&gt;#   =&amp;gt; ~/dev/my-app/tooling&lt;/span&gt;
  &lt;span class="k"&gt;function &lt;/span&gt;cd_from_git_root&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;root
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-}&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;base_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;subpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

    &lt;span class="c"&gt;# if no argument provided, set default path&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="c"&gt;# Extract base key and subpath&lt;/span&gt;
    &lt;span class="nv"&gt;base_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;input&lt;/span&gt;:0:1&lt;span class="k"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;subpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;input&lt;/span&gt;:2&lt;span class="k"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;# Define key =&amp;gt; path mappings&lt;/span&gt;
    &lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; key_to_base_path
    key_to_base_path[a]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"apps"&lt;/span&gt;
    key_to_base_path[p]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"packages"&lt;/span&gt;
    key_to_base_path[t]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"tooling"&lt;/span&gt;

    &lt;span class="c"&gt;# Define specific shortcut =&amp;gt; path mappings&lt;/span&gt;
    &lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; shortcuts
    shortcuts[a/w]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"apps/webapp"&lt;/span&gt;
    shortcuts[a/m]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"apps/marketing"&lt;/span&gt;
    shortcuts[a/d]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"apps/docs"&lt;/span&gt;

    &lt;span class="c"&gt;# Check for specific shortcuts first&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;shortcuts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;shortcuts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key_to_base_path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$base_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key_to_base_path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$base_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$subpath&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else
      &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="c"&gt;# Remove leading slash if present&lt;/span&gt;
    &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"s/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="s2"&gt;//"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git_root&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1  &lt;span class="c"&gt;# Get git root using custom git_root function&lt;/span&gt;
    &lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1  &lt;span class="c"&gt;# Navigate to the path or return an error&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;# add convenient names&lt;/span&gt;
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;cdr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd_from_git_root'&lt;/span&gt;
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cd_from_git_root'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scaffolding folders
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# Overview:&lt;/span&gt;
  &lt;span class="c"&gt;#  A custom implementation of the mkdir command that scaffolds a folder and inner files&lt;/span&gt;
  &lt;span class="c"&gt;#  first argument is the folder name&lt;/span&gt;
  &lt;span class="c"&gt;#  second argument is a string of options&lt;/span&gt;
  &lt;span class="c"&gt;#  options:&lt;/span&gt;
  &lt;span class="c"&gt;#   - s: (Story)  =&amp;gt; generate story file (folder_name.story.tsx)&lt;/span&gt;
  &lt;span class="c"&gt;#   - d: (Docs)   =&amp;gt; generate docs file (folder_name.mdx)&lt;/span&gt;
  &lt;span class="c"&gt;#   - r: (React)  =&amp;gt; make all generated files .tsx instead of .ts &lt;/span&gt;
  &lt;span class="c"&gt;#   - t: (Test)   =&amp;gt; generate test file (folder_name.test.tsx)&lt;/span&gt;
  &lt;span class="c"&gt;# Usage examples:&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; mkdir+ my-component rst&lt;/span&gt;
  &lt;span class="c"&gt;#   creates:&lt;/span&gt;
  &lt;span class="c"&gt;#     my-component&lt;/span&gt;
  &lt;span class="c"&gt;#       - index.ts&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-component.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-component.story.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-component.test.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; mkdir+ my-component s&lt;/span&gt;
  &lt;span class="c"&gt;#   creates:&lt;/span&gt;
  &lt;span class="c"&gt;#     my-component&lt;/span&gt;
  &lt;span class="c"&gt;#       - index.ts&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-component.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-component.story.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="c"&gt;#   ~/dev/my-app&amp;gt; mkdir+ my-util t&lt;/span&gt;
  &lt;span class="c"&gt;#   creates:&lt;/span&gt;
  &lt;span class="c"&gt;#     my-util&lt;/span&gt;
  &lt;span class="c"&gt;#       - index.ts&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-util.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#       - my-util.test.tsx&lt;/span&gt;
  &lt;span class="c"&gt;#------------------------&lt;/span&gt;
  &lt;span class="nb"&gt;mkdir&lt;/span&gt;+&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="c"&gt;# get values from arguments&lt;/span&gt;
      &lt;span class="nv"&gt;folder_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
      &lt;span class="nv"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;

      &lt;span class="c"&gt;# Default options&lt;/span&gt;
      &lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; opt
      opt[test]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;  &lt;span class="c"&gt;# Could set to true if you want to generate test files by default&lt;/span&gt;
      opt[story]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;
      opt[docs]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;
      opt[react]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;

      &lt;span class="c"&gt;# Update options based on the input string&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$options&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="s2"&gt;"s"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;opt[story]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;
      &lt;span class="k"&gt;fi
      if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$options&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="s2"&gt;"d"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;opt[docs]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;
      &lt;span class="k"&gt;fi
      if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$options&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;opt[react]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;
      &lt;span class="k"&gt;fi
      if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$options&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="s2"&gt;"t"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;opt[test]&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;
      &lt;span class="k"&gt;fi&lt;/span&gt;

      &lt;span class="c"&gt;# Set file extension based on React option&lt;/span&gt;
      &lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ts"&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;[react]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"tsx"&lt;/span&gt;
      &lt;span class="k"&gt;fi&lt;/span&gt;

      &lt;span class="c"&gt;# Create folder and base files&lt;/span&gt;
      &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"index.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export * from './&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;';"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"index.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      code &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

      &lt;span class="c"&gt;# Generate test file by default&lt;/span&gt;
      &lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;.test.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

      &lt;span class="c"&gt;# Generate story file if 's' is present&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;[story]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;.story.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_extension&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;fi&lt;/span&gt;

      &lt;span class="c"&gt;# Generate docs file if 'd' is present&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;[docs]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$folder_name&lt;/span&gt;&lt;span class="s2"&gt;.mdx"&lt;/span&gt;
      &lt;span class="k"&gt;fi&lt;/span&gt;

      &lt;span class="c"&gt;# navigate back to where the command was run so that the user can create multiple folders&lt;/span&gt;
      &lt;span class="nb"&gt;cd&lt;/span&gt; ..
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Evaluation of git alias vs node.js code gen tools
&lt;/h3&gt;

&lt;p&gt;Combining this approach of absolute navigation (&lt;code&gt;r&lt;/code&gt; alias) with the folder scaffolding alias (&lt;code&gt;mkdir+&lt;/code&gt;) can it super fast to build out a project. This has a significant speed advantage when compared to using node.js codegen tools like plop.js as it only uses bash and therefore can execute the commands without starting up a node.js server.&lt;/p&gt;

&lt;p&gt;Although using plop.js is more well for usecases where you have a predictable boilerplate pattern that you reuse frequently. This is because plop enables you to more easily define the contents of the file by using the handlebars templating langauge. I do not recommend trying to define similar templates using bash.&lt;/p&gt;

&lt;p&gt;I personally use plop for defining UI components as they all share a similar syntax for the stories / testing / definition file.  Let me know if you are interested in accessing my code generation files and I may write another post to share them with you.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Incorporating these Git aliases into your daily routine can significantly enhance your productivity. For further resources on coding efficiency, check out my other posts on snippets and monorepo management.&lt;/p&gt;

&lt;p&gt;Thank you for your time and engagement. If you found this post helpful or have your own snippets to share, I’d love to hear from you in the comments.&lt;/p&gt;

&lt;h3&gt;
  
  
  About the author:
&lt;/h3&gt;

&lt;p&gt;Thanks for reading! I’m Dawid, founder of Ream and a software engineer passionate about integrating technology with holistic personal growth. My experience in psychology, computer science, and business has fuelled my drive to create human-centric digital tools. This blog reflects my commitment to practical, efficient solutions in software engineering and beyond. If you found this post helpful or want to connect, feel free to reach out. Let’s continue to learn and grow together in our tech journeys.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>webdev</category>
      <category>monorepo</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
