<?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: F1LT3R </title>
    <description>The latest articles on Forem by F1LT3R  (@f1lt3r).</description>
    <link>https://forem.com/f1lt3r</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%2F117683%2Ff800f0b5-4575-4974-a0dc-693ca757db68.jpg</url>
      <title>Forem: F1LT3R </title>
      <link>https://forem.com/f1lt3r</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/f1lt3r"/>
    <language>en</language>
    <item>
      <title>A Reasonably Simple, Secure Password Scheme</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Thu, 14 Aug 2025 22:25:19 +0000</pubDate>
      <link>https://forem.com/f1lt3r/a-reasonably-simple-secure-password-scheme-4890</link>
      <guid>https://forem.com/f1lt3r/a-reasonably-simple-secure-password-scheme-4890</guid>
      <description>&lt;h1&gt;
  
  
  A Simple Password Scheme
&lt;/h1&gt;

&lt;p&gt;Are online password generators and password library systems  really safe and secure?&lt;/p&gt;

&lt;p&gt;With a across-site attack, someone may be able to read the password you are generating online. And hackers can and do attack centralized password library databases, to steal the database files and crack as many of the passwords as possible. &lt;/p&gt;

&lt;p&gt;This happened to the password service LastPass in 2022: &lt;a href="https://techcrunch.com/2022/12/22/lastpass-customer-password-vaults-stolen/" rel="noopener noreferrer"&gt;https://techcrunch.com/2022/12/22/lastpass-customer-password-vaults-stolen/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article you will learn a reasonably simple password scheme that you can use across many services without worrying about your passwords being hacked, because we never have to store the passwords anywhere, even on paper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A linux terminal.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;dicewords&lt;/code&gt; program.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;pwgen&lt;/code&gt; program.&lt;/li&gt;
&lt;li&gt;Stickers (or other device name system).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;diceware pwgen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generate A Scheme Passphrase
&lt;/h2&gt;

&lt;p&gt;The goal is to come up with a password with the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to remember (simple, memorable words or phrase)&lt;/li&gt;
&lt;li&gt;Hard to brute-force (high entropy)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Diceware
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the &lt;code&gt;Diceware&lt;/code&gt; utility if you do not have it already:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;diceware
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now use &lt;code&gt;Diceware&lt;/code&gt; to generate a 7 word phrase with a couple of special characters thrown in:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;diceware &lt;span class="nt"&gt;-n&lt;/span&gt; 7 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- `-n 7` - Number: Select seven random words.
- `-d " "` - Delimiter: separate the words with a space.
- `-s 2` - Special Chars: Change two characeters to special characters.

The resulting output should be something like:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```plaintext
Idealness Revivi5g Delir$ous Presuming Badge Straggler Sworn
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; **NOTE:** the two special characters above are `5` and `$`. These characters raise the entropy of your password, making it hard to brute-force.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Storing Your Scheme Passphrase
&lt;/h3&gt;

&lt;p&gt;Seven words and two special characters should be easy enough to memorize. If you &lt;strong&gt;have&lt;/strong&gt; to write it down to remember the phrase, my suggestion is to follow these three basic rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Only keep it written down for a month or so.&lt;/li&gt;
&lt;li&gt;Keep the paper you've written it on under locked and key.&lt;/li&gt;
&lt;li&gt;When you have memorized the passphrase, burn the paper.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It shouldn't take you long to memorize, as you will be using it fairly often when you need to log into a service, or system.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Password Scheme
&lt;/h2&gt;

&lt;p&gt;With this reasonably simple password scheme, you only have to remember five things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;PASSPHRASE&lt;/code&gt; - Your Scheme Passphrase, as generated above.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DOMAIN&lt;/code&gt; - The name of the device, domain or service you are using.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IDENTITY&lt;/code&gt; - The username, email, or phone number you use with that device, domain, or service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LENGTH&lt;/code&gt; - The length of the password for your domain. Some passwords systems are limited in length.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MODE&lt;/code&gt; - The mode is either &lt;code&gt;SIMPLE&lt;/code&gt; (uses basic characters), or &lt;code&gt;COMPLEX&lt;/code&gt; (uses lots of special characters). Some password systems to not allow complex passwords.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can visualize your password scheme this way:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PASSPHRASE &amp;gt; DOMAIN + IDENTITY &amp;lt; [LENGTH, MODE] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;PASSPHRASE&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Your &lt;code&gt;PASSPHRASE&lt;/code&gt; is the Scheme Passphrase you used above.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;DOMAIN&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;DOMAIN&lt;/code&gt; is the thing your are using your passphrase to log into. The &lt;code&gt;DOMAIN&lt;/code&gt; can be a physical computer, a web domain, a physical or virtual disk,etc.&lt;/p&gt;

&lt;p&gt;Naming your domain is easy, just take the web address of the service you are using, for example: "&lt;code&gt;twitter.com&lt;/code&gt;".&lt;/p&gt;

&lt;h4&gt;
  
  
  Naming Physical Devices
&lt;/h4&gt;

&lt;p&gt;You may want to commit the names of your devices to memory, such as &lt;code&gt;Backup-Disc-1&lt;/code&gt; or &lt;code&gt;Main-Computer&lt;/code&gt;. But if you have a lot of physical devices that require a password, you may want to use a naming strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I encourage you to generate your own device naming system that is most memorable for you. But here is an example to help get you thinking:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buy an assortment of stickers: letters, numbers, color dots, animals, plants, spaceships, cartoon characters, etc.&lt;/li&gt;
&lt;li&gt;Give each device one or more stickers.&lt;/li&gt;
&lt;li&gt;Generate a name from the stickers you placed on the device, for example: if you placed a red dot sticker, a gopher animal sticker and a number 2 sticker to the device, it's &lt;code&gt;DOMAIN&lt;/code&gt; might be something like: "&lt;code&gt;RedGopher2&lt;/code&gt;"&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;  You may use multiple passwords to log into a computer system if you have set a BIOS password, or use disc encryption. In this case you can add this detail to your &lt;code&gt;DOMAIN&lt;/code&gt;, eg: "&lt;code&gt;RedGopher2-BIOS&lt;/code&gt;".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;USER&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;USER&lt;/code&gt; is simply the username you use when logging into a particular domain. &lt;/p&gt;

&lt;p&gt;For a website or service, your &lt;code&gt;USER&lt;/code&gt; will be your email address or username.&lt;/p&gt;

&lt;p&gt;For a physical computer system, your &lt;code&gt;USER&lt;/code&gt; will be the main username you use to log into the operating system.&lt;/p&gt;

&lt;p&gt;For a physical disk, your &lt;code&gt;USER&lt;/code&gt; can just be "&lt;code&gt;user&lt;/code&gt;" or your name.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;LENGTH&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Some websites and computer BIOS passwords are limited in the length of characters allowed, and also the complexity of special characters allowed. So the length of the password will be subject to the password system you are logging into.&lt;/p&gt;

&lt;p&gt;My suggestion is to only use two or three &lt;code&gt;LENGTH&lt;/code&gt; + &lt;code&gt;MODE&lt;/code&gt; pairs where possible to reduce the complexity for memorization.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;LENGTH=64&lt;/code&gt; + &lt;code&gt;MODE="COMPLEX"&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Disk Encryption Passwords&lt;/li&gt;
&lt;li&gt;Most Website Passwords&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x1THK''[zH5=&amp;gt;VJylQfJs9EK4[[/w.q*#U4;bP=pRw9++?\-MK#"Z(ND=UhY=\vH
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;LENGTH=16&lt;/code&gt; + &lt;code&gt;MODE="SIMPLE"&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;BIOS passwords&lt;/li&gt;
&lt;li&gt;Poorly designed website passwords&lt;/li&gt;
&lt;li&gt;Mobile passwords&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;en8ae4Poh0Fahgh5
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; While many BIOS systems will allow a long, complex password; they may be very time consuming to type into a terminal where you are unable to copy + paste the password. It is sometimes acceptable (as a necessary limitation) to use a short, simple password for these password checkpoints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Scheme Table
&lt;/h3&gt;

&lt;p&gt;Let's say you want to log into your desktop computer, then log into an external drive, and finally log into Twitter. Your Scheme Table might look like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Checkpoint&lt;/th&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Identity&lt;/th&gt;
&lt;th&gt;Length&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Desktop Computer&lt;/td&gt;
&lt;td&gt;BIOS Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RedGopher2-BIOS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"user"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop Computer&lt;/td&gt;
&lt;td&gt;Disk Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RedGopher2-DISK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"user"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop Computer&lt;/td&gt;
&lt;td&gt;OS Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RedGopher2-OS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"user"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External Disk&lt;/td&gt;
&lt;td&gt;Disk Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BlueDuck3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"user"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COMPLEX&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twitter&lt;/td&gt;
&lt;td&gt;Web Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;twitter.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"me@domain.com"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COMPLEX&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Generating Passwords to Scheme
&lt;/h2&gt;

&lt;p&gt;Using the Password Scheme Table above, let's generate a set of passwords.&lt;/p&gt;

&lt;p&gt;To generate a &lt;code&gt;SIMPLE&lt;/code&gt; password for the Desktop Computer's BIOS we use &lt;code&gt;pwgen&lt;/code&gt; with a &lt;code&gt;SEED&lt;/code&gt;. The &lt;code&gt;SEED&lt;/code&gt; is used to generate the password, meaning the password will always be easily recoverable by remembering the &lt;code&gt;PASSPHRASE&lt;/code&gt; + &lt;code&gt;DOMAIN&lt;/code&gt; : &lt;code&gt;USER&lt;/code&gt; with the &lt;code&gt;LENGTH&lt;/code&gt; and &lt;code&gt;MODE&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Idealness Revivi5g Delir$ous Presuming Badge Straggler Sworn'&lt;/span&gt;
&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'RedGopher2-BIOS'&lt;/span&gt;
&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'user'&lt;/span&gt;
&lt;span class="nv"&gt;SEED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSPHRASE&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Use the seed to generate a password&lt;/span&gt;
pwgen 16 1 &lt;span class="nt"&gt;-H&lt;/span&gt; &amp;lt;&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;$SEED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-cn&lt;/span&gt;

&lt;span class="c"&gt;# OUTPUT: "cheekuCho2quaula"&lt;/span&gt;

&lt;span class="c"&gt;# Clear sensitive variables from memory (or close terminal)&lt;/span&gt;
&lt;span class="nv"&gt;PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CHALLENGE:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Try generating the password using the information above. Do you get the same output: "&lt;code&gt;cheekuCho2quaula&lt;/code&gt;"?  &lt;/p&gt;

&lt;p&gt;You should!   &lt;/p&gt;

&lt;p&gt;Try changing one of the words and getting a new password output. Then switch the word you changed, back to it's original word, and you should get your original generated password back again: "&lt;code&gt;cheekuCho2quaula&lt;/code&gt;".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can do the same again for the &lt;code&gt;COMPLEX&lt;/code&gt; passwords with a &lt;code&gt;LENGTH&lt;/code&gt; of 64 characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Idealness Revivi5g Delir$ous Presuming Badge Straggler Sworn'&lt;/span&gt;
&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'twitter.com'&lt;/span&gt;
&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'me@domain.com'&lt;/span&gt;
&lt;span class="nv"&gt;SEED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSPHRASE&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Use the seed to generate a password&lt;/span&gt;
pwgen 64 1 &lt;span class="nt"&gt;-H&lt;/span&gt; &amp;lt;&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;$SEED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-cnsy&lt;/span&gt;

&lt;span class="c"&gt;# OUTPUT: "cheekuCho2quaula"&lt;/span&gt;

&lt;span class="c"&gt;# Clear sensitive variables from memory (or close terminal)&lt;/span&gt;
&lt;span class="nv"&gt;PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameters we changed were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"&lt;code&gt;pwqgen 64&lt;/code&gt;" - Produce a 64 character length password.&lt;/li&gt;
&lt;li&gt;"&lt;code&gt;pwgen -s&lt;/code&gt;" - Create a secure password with complex high entropy character set.&lt;/li&gt;
&lt;li&gt;"&lt;code&gt;pwgen -y&lt;/code&gt;" - Use symbol/special characters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Processing The Whole Table
&lt;/h3&gt;

&lt;p&gt;When we apply the the logic above to the whole Scheme Table, we get the following output:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Checkpoint&lt;/th&gt;
&lt;th&gt;Password&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Desktop Computer&lt;/td&gt;
&lt;td&gt;BIOS Password&lt;/td&gt;
&lt;td&gt;"&lt;code&gt;cheekuCho2quaula&lt;/code&gt;"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop Computer&lt;/td&gt;
&lt;td&gt;Disk Password&lt;/td&gt;
&lt;td&gt;"&lt;code&gt;iGahghoog9Ahgh7N&lt;/code&gt;"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop Computer&lt;/td&gt;
&lt;td&gt;OS Password&lt;/td&gt;
&lt;td&gt;"&lt;code&gt;ahghun7Shauweew0&lt;/code&gt;"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External Disk&lt;/td&gt;
&lt;td&gt;Disk Password&lt;/td&gt;
&lt;td&gt;"`yN2F/_T}&amp;amp;#!Y68^_q%ZmoYt]xc?l%qf&amp;lt;&amp;lt;!(u,:hc%Od\&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twitter&lt;/td&gt;
&lt;td&gt;Web Password&lt;/td&gt;
&lt;td&gt;"{% raw %}&lt;code&gt;z12-Qxyg{s9Ua~g0bAUG`N-pm7NAujx4hno&amp;lt;C(5\asM4]/`xg0^tCjK$06q=8gCn&lt;/code&gt;"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Using a Generator Script
&lt;/h2&gt;

&lt;p&gt;To make it easy to retrieve your passwords quickly, you can create a generator script within your bin &lt;code&gt;$PATH&lt;/code&gt;. We will simply name our generator script "&lt;code&gt;pass&lt;/code&gt;". Don't forget to run &lt;code&gt;chmod +x ./pass&lt;/code&gt;, to make the generator executable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# The first arg is your DOMAIN:USER (string)&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="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"You must provide a DOMAIN:USER, eg: 'twitter.com:me@domain.com'"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;DOMAIN_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Use a secure password entry for your PASSPHRASE&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; Enter your PASSPHRASE: 
&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; PASSPHRASE
&lt;span class="nb"&gt;echo&lt;/span&gt;

&lt;span class="c"&gt;# The second arg is password LENGTH&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="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;# Default to 64 characters for most passwords&lt;/span&gt;
    &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nv"&gt;LENGTH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;# We can pass a custom length, "16", for our working example&lt;/span&gt;
    &lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;LENGTH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# The third argument is our MODE&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="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;# Default to SECURE for most passwords&lt;/span&gt;
    &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"SECURE"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;# Providing any input, eg: [y, true, simple] -sets MODE to SIMPLE&lt;/span&gt;
    &lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"SIMPLE"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Create our recoverable SEED&lt;/span&gt;
&lt;span class="nv"&gt;SEED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSPHRASE&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN_USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Generate password based on LENGTH, SEED and MODE&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MODE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"SIMPLE"&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;PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pwgen &lt;span class="nv"&gt;$LENGTH&lt;/span&gt; 1 &lt;span class="nt"&gt;-H&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SEED&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="nt"&gt;-cny&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pwgen &lt;span class="nv"&gt;$LENGTH&lt;/span&gt; 1 &lt;span class="nt"&gt;-H&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$SEED&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="nt"&gt;-cnsy&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$PASS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using our "&lt;code&gt;pass&lt;/code&gt;" script we can generate our Twitter password as described in the examples above. You will be asked to enter your &lt;code&gt;PASSPHRASE&lt;/code&gt;. As you type your &lt;code&gt;PASSPHRASE&lt;/code&gt; out, your characters will be hidden.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pass &lt;span class="s1"&gt;'twitter.com:me@domain.com'&lt;/span&gt;

Enter your PASSPHRASE:

&lt;span class="c"&gt;# OUTPUT: z12-Qxyg{s9Ua~g0bAUG`N-pm7NAujx4hno&amp;lt;C(5\asM4]/`xg0^tCjK$06q=8gCn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Further Strategies to Consider
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Memorable Words
&lt;/h3&gt;

&lt;p&gt;Make sure you pick words that are memorable to you!&lt;/p&gt;

&lt;p&gt;Try to pick words that have some meaning to your life. This will make them much easier to remember. This is especially true if the commination of your words tell some kind of story.&lt;/p&gt;

&lt;h3&gt;
  
  
  Only Four Words for Beginners
&lt;/h3&gt;

&lt;p&gt;For beginners: consider keeping your &lt;code&gt;PASSPHRASE&lt;/code&gt; to four words.&lt;/p&gt;

&lt;p&gt;Keeping your &lt;code&gt;PASSPHRASE&lt;/code&gt; to four words will make this simple password scheme easier to use and quicker to memorize. When you are comfortable with this simple password system, consider upgrading to seven words.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a &lt;code&gt;SALTWORD&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You may want to add a &lt;code&gt;SALTWORD&lt;/code&gt; to your &lt;code&gt;DOMAIN&lt;/code&gt;:&lt;code&gt;USER&lt;/code&gt; string for extra obfuscation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pass &lt;span class="s1"&gt;'twitter.com:me@domain.com+FOOBAR'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can easily change your &lt;code&gt;SALTWORD&lt;/code&gt; to be individualized to a &lt;code&gt;DOMAIN&lt;/code&gt;, or use the same &lt;code&gt;SALTWORD&lt;/code&gt; across multiple domains. Just make sure you create a memorable scheme for your saltwords if you use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Domain Breech
&lt;/h3&gt;

&lt;p&gt;If you learn that a hacker has breeched any given domain, you can add a &lt;code&gt;SALTWORD&lt;/code&gt; for the specific domains that were breeched.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Domain or &lt;code&gt;PASSPHRASE&lt;/code&gt; Breech
&lt;/h3&gt;

&lt;p&gt;If you learn, or suspect that someone has gained access to your &lt;code&gt;PASSPHRASE&lt;/code&gt;, I would recommend taking the following action:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Generate a new &lt;code&gt;PASSPHRASE&lt;/code&gt; if you're sure someone has all your words. Or you may want to change a single word in your &lt;code&gt;PASSPHRASE&lt;/code&gt; if you only suspect someone has gain accessed to your words.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a table of your domains (like the one earlier in this document).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use a bash script to run through your domains and generate a new set of passwords. Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; Enter your new PASSPHRASE: 
&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; NEW_PASSPHRASE
&lt;span class="nb"&gt;echo

&lt;/span&gt;newPass &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&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="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&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;PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pwgen &lt;span class="nv"&gt;$2&lt;/span&gt; 1 &lt;span class="nt"&gt;-H&lt;/span&gt; &amp;lt;&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;$NEW_PASSPHRASE&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-cnsy&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="nv"&gt;PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pwgen &lt;span class="nv"&gt;$2&lt;/span&gt; 1 &lt;span class="nt"&gt;-H&lt;/span&gt; &amp;lt;&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;$NEW_PASSPHRASE&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-cn&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fi

    &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;$1&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="nv"&gt;$PASS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

newPass &lt;span class="s2"&gt;"RedGopher2-BIOS:user"&lt;/span&gt; 16 SIMPLE
newPass &lt;span class="s2"&gt;"RedGopher2-DISK:user"&lt;/span&gt; 16 SIMPLE
newPass &lt;span class="s2"&gt;"RedGopher2-OS:user"&lt;/span&gt; 16 SIMPLE
newPass &lt;span class="s2"&gt;"BlueDuck3:user"&lt;/span&gt; 64
newPass &lt;span class="s2"&gt;"twitter.com:me@domain.com"&lt;/span&gt; 64
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;After running the script with "&lt;code&gt;F0o Bar Ba$ Qux&lt;/code&gt;" as your &lt;code&gt;PASSPHRASE&lt;/code&gt;, you should see the following output:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Enter your new PASSPHRASE:

&lt;span class="s2"&gt;"RedGopher2-BIOS:user"&lt;/span&gt;: piec5Oovaaloh8pe
&lt;span class="s2"&gt;"RedGopher2-DISK:user"&lt;/span&gt;: Iquathae5na3aL2m
&lt;span class="s2"&gt;"RedGopher2-OS:user"&lt;/span&gt;: ouSohS8pei3yee6i

&lt;span class="s2"&gt;"BlueDuck3:user"&lt;/span&gt;: &lt;span class="o"&gt;]&lt;/span&gt;v&lt;span class="o"&gt;)&lt;/span&gt;Dy&lt;span class="s1"&gt;'rTSBbkwN7Dns=z&amp;lt;T0CZcID!D[Q42/i=q(nD@\Kg@/^mr0(f2"wQFsPC~&amp;gt;}

"twitter.com:me@domain.com": &amp;gt;,D\-c.6'&lt;/span&gt;+G]-:!PIEeOp6?&lt;span class="p"&gt;;&lt;/span&gt;B&lt;span class="s1"&gt;'yP=UsPzCu`rd6HSY0b}gtS^z61dZc;6Yp=Spg9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Congratulations!&lt;/p&gt;

&lt;p&gt;Now you can quickly recover a seeded password for any domain using a memorable &lt;code&gt;PASSPHRASE&lt;/code&gt; on any system with &lt;code&gt;pwgen&lt;/code&gt; installed.&lt;/p&gt;

&lt;p&gt;If you learn of a breech you can update your passwords individually with a &lt;code&gt;SALTWORD&lt;/code&gt;, or update all your all passwords with a new &lt;code&gt;PASSPHRASE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This password system is easy to remember, simple to use and only requires one tool to be installed (&lt;code&gt;pwgen&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This password system does not rely on any centralized services prone to hackers, and if you're comfortable memorizing a few words, you never have to write any passwords down!&lt;/p&gt;

</description>
      <category>security</category>
      <category>dicewords</category>
      <category>pwgen</category>
      <category>password</category>
    </item>
    <item>
      <title>LUKS Encrypt 🔐 Raspberry PI 🍓🥧</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Mon, 08 Jan 2024 04:57:01 +0000</pubDate>
      <link>https://forem.com/f1lt3r/luks-encrypt-raspberry-pi-2ei8</link>
      <guid>https://forem.com/f1lt3r/luks-encrypt-raspberry-pi-2ei8</guid>
      <description>&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Raspberry PI&lt;/li&gt;
&lt;li&gt;SDCard w/ Raspberry PI OS Lite installed&lt;/li&gt;
&lt;li&gt;Flash drive connected to the RPI (to copy data from root partition during encrypt)&lt;/li&gt;
&lt;li&gt;Bash scripts: &lt;a href="https://github.com/F1LT3R/luks-encrypt-raspberry-pi"&gt;https://github.com/F1LT3R/luks-encrypt-raspberry-pi&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Install OS and Update Kernel
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Burn the Raspberry PI OS to the SDCard w/ &lt;code&gt;Balenar Etcher&lt;/code&gt; or &lt;code&gt;Raspberry PI Imager&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy install scripts into &lt;code&gt;/boot/install/&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Boot into the Raspberry PI and run &lt;code&gt;sudo /boot/install/1.update.sh&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;sudo reboot&lt;/code&gt;  to load the updated kernel&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Install Enc Tools and Prep &lt;code&gt;initramfs&lt;/code&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run script &lt;code&gt;/boot/install/2.disk_encrypt.sh&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;sudo reboot&lt;/code&gt; to drop into the initramfs shell. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mount and Encrypt
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Mount master block device to &lt;code&gt;/tmp/boot/&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /tmp/boot
mount /dev/mmcblk0p1 /tmp/boot/
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the encryption script, passing your flash drive descriptor:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/tmp/boot/install/3.disk_encrypt_initramfs.sh &lt;span class="o"&gt;[&lt;/span&gt;sda|sdb|etc] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When LUKS encrypts the root partition it will ask you to type &lt;code&gt;YES&lt;/code&gt; (in uppercase).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a decryption password (you will be asked twice).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LUKS will ask for the decryption password again to copy the data back from the flash drive to the root partition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;reboot -f&lt;/code&gt; to drop back into initramfs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Unlock and Reboot to OS
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Mount master block device at &lt;code&gt;/tmp/boot/&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /tmp/boot
mount /dev/mmcblk0p1 /tmp/boot/
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the LUKS encrypted disk:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/tmp/boot/install/4.luks_open.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type in your decryption password again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;exit&lt;/code&gt; to quit BusyBox and boot normally.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rebuild &lt;code&gt;initramfs&lt;/code&gt; for Normal Boot
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Run script: &lt;code&gt;/boot/install/5.rebuild_initram.sh&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;sudo reboot&lt;/code&gt; into Raspberry PI OS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You should be asked for your decryption password every time you boot.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Please unlock disc sdcard: _
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Source: &lt;a href="https://forums.raspberrypi.com/viewtopic.php?t=219867"&gt;https://forums.raspberrypi.com/viewtopic.php?t=219867&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/johnshearing/MyEtherWalletOffline/blob/master/Air-Gap_Setup.md#setup-luks-full-disk-encryption"&gt;https://github.com/johnshearing/MyEtherWalletOffline/blob/master/Air-Gap_Setup.md#setup-luks-full-disk-encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://robpol86.com/raspberry_pi_luks.html"&gt;https://robpol86.com/raspberry_pi_luks.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.howtoforge.com/automatically-unlock-luks-encrypted-drives-with-a-keyfile"&gt;https://www.howtoforge.com/automatically-unlock-luks-encrypted-drives-with-a-keyfile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>raspberrypi</category>
      <category>luks</category>
      <category>tutorial</category>
      <category>security</category>
    </item>
    <item>
      <title>Using LUKS Encrypted 🔐 Disks w/ Linux 🐧 on The CLI</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Mon, 08 Jan 2024 02:54:43 +0000</pubDate>
      <link>https://forem.com/f1lt3r/using-luks-encrypted-disks-w-linux-on-cli-ha9</link>
      <guid>https://forem.com/f1lt3r/using-luks-encrypted-disks-w-linux-on-cli-ha9</guid>
      <description>&lt;p&gt;In this scenario, I create an encrypted LUKS disk to periodically save the &lt;code&gt;Documents/&lt;/code&gt; folder with Rsync, from a computer that does not have a GUI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a LUKS Disk
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Snapshot the disk list&lt;/span&gt;
&lt;span class="nv"&gt;BEFORE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; lsblk &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BEFORE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# [PLUG IN DISK]&lt;/span&gt;

&lt;span class="c"&gt;# Snapshot changed disk list&lt;/span&gt;
&lt;span class="nv"&gt;AFTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; lsblk &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AFTER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Show the disks changed&lt;/span&gt;
diff &lt;span class="nt"&gt;-U0&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BEFORE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AFTER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; +4

&lt;span class="c"&gt;# Remove tmps&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BEFORE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$AFTER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Setup luksFormat Disk&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;cryptsetup luksFormat /dev/xvdj

&lt;span class="c"&gt;# [TYPE "YES"]&lt;/span&gt;
&lt;span class="c"&gt;# [Enter Password]&lt;/span&gt;
&lt;span class="c"&gt;# [Enter Confirmation Password]&lt;/span&gt;

&lt;span class="c"&gt;# Open Encrypted Partition&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;cryptsetup luksOpen /dev/xvdj DATA

&lt;span class="c"&gt;# Install XFS Tools is necessary &lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;xfsprogs

&lt;span class="c"&gt;# Add XFS File System&lt;/span&gt;
&lt;span class="c"&gt;# (sudo apt install xfsprogs)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mkfs.xfs /dev/mapper/DATA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Mounting a LUKS Disk
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Attach disk to Qube &lt;/span&gt;

&lt;span class="c"&gt;# Replace xvdi, DATA with actual names&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;cryptsetup luksOpen /dev/xvdi DATA

&lt;span class="c"&gt;# See drive on mapper&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; /dev/mapper/DATA

&lt;span class="c"&gt;# Create mount point&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /media/user/DATA

&lt;span class="c"&gt;# Mount the partition&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/mapper/DATA /media/user/DATA

&lt;span class="c"&gt;# Rsync ~/Documents, excluding node_modules&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;rsync &lt;span class="nt"&gt;-av&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"node_modules:*.un~"&lt;/span&gt; ~/Documents /media/user/DATA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Unmounting a LUKS Disk
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Unmount the disk&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;umount /media/user/DATA

&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; /media/user/DATA

&lt;span class="c"&gt;# Close the encrypted partition&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;cryptsetup luksClose DATA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>luks</category>
      <category>cryptsetup</category>
      <category>disk</category>
      <category>rsync</category>
    </item>
    <item>
      <title>Do You Remember "Semantic HTML"? 🤣</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Fri, 29 Dec 2023 17:11:55 +0000</pubDate>
      <link>https://forem.com/f1lt3r/do-you-remember-semantic-html-42</link>
      <guid>https://forem.com/f1lt3r/do-you-remember-semantic-html-42</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getLabelProps&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;Enter a fruit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
    &lt;span class="na"&gt;style&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="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inline-block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getRootProps&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;suppressRefError&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="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;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="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getInputProps&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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getMenuProps&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;isOpen&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;inputValue&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;item&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="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;getItemProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&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="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="nx"&gt;highlightedIndex&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightgray&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;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;selectedItem&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bold&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;normal&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;li&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;span class="kc"&gt;null&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;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>ShadeJS 🌴 Part 2 - The Magic HTTP Server 💫</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Wed, 20 Dec 2023 04:19:13 +0000</pubDate>
      <link>https://forem.com/f1lt3r/shadejs-part-2-the-magic-http-server-3467</link>
      <guid>https://forem.com/f1lt3r/shadejs-part-2-the-magic-http-server-3467</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is &lt;strong&gt;Part 2&lt;/strong&gt; of the series: &lt;strong&gt;Build Your Own SPA Framework with Modular JavaScript, NodeJS and Closed-Shadow Web Components&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://dev.to/f1lt3r/build-a-spa-framework-1-4jld"&gt;Part 1&lt;/a&gt;  |  Part 2&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Journey Continues
&lt;/h2&gt;

&lt;p&gt;So I got a logo 🌴&lt;/p&gt;

&lt;p&gt;And I grabbed some namespaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/~shadejs" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Shade-JS/ShadeJS/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://shadejs.com/" rel="noopener noreferrer"&gt;ShadeJS.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's time to start working on the HTTP server!&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Design
&lt;/h2&gt;

&lt;p&gt;I'll be honest. I hate using bundlers and transpilers. But one of the things I love about them, is the way that imports don't require a file extension.&lt;/p&gt;

&lt;p&gt;For example:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;foo&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;./foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// imports ./foo.mjs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also the ability to get &lt;code&gt;index.mjs&lt;/code&gt; from it's component directory.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;foo&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;./my-comp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// imports ./my-comp/index.mjs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rewrites
&lt;/h2&gt;

&lt;p&gt;When you setup a web server such as Apache, or Nginx, the server is already using these kind of rules. They are called "rewrites". That's how the server knows to fetch &lt;code&gt;index.html&lt;/code&gt; when being asked for the root &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I will need a stack of rewrite rules to check through.&lt;/p&gt;

&lt;p&gt;Like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rewritePaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/index.html`&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;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.html`&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;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.mjs`&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;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/index.mjs`&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;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.css`&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;pathname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/index.css`&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;Now we need to add some logic to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check for the file if a file extension was found in the request.&lt;/li&gt;
&lt;li&gt;Check the rewrite paths if there was no extension.&lt;/li&gt;
&lt;li&gt;Return the OS file location, content-type, etc.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rewrite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extension&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;rewrites&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extension&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;removeDoubleSlashes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rewritePaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for &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;rewrite&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;rewrites&lt;/span&gt;&lt;span class="p"&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;rewriteTarget&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;stripStartSlash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rewrite&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;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rewriteTarget&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;stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getStat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rewriteTarget&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ext&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;stat&lt;/span&gt;&lt;span class="p"&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="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentType&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But UT-OH.&lt;/p&gt;

&lt;p&gt;I've broken something!&lt;/p&gt;

&lt;p&gt;Relative imports no longer work. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fccmas3yqwyffh1eqe6sa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fccmas3yqwyffh1eqe6sa.png" alt="Code 404 in Browsers Developer Tools" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  301 Moved Permanently
&lt;/h2&gt;

&lt;p&gt;When I'm serving a response without the file extension, and that response uses a file import, the browser does not know what that new import is relative to. This breaks my relative imports, throwing a 404 response code.&lt;/p&gt;

&lt;p&gt;To handle this I will use the 301 Moved Permanently response code.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasNoEndSlash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wasRewritten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&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;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;WEB_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&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;MovedPermanently301&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&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;location&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;301 Moved Permanently&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&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;requestHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="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="nf"&gt;hasNoEndSlash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;wasRewritten&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&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;relativeLocation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;WEB_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;MovedPermanently301&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;relativeLocation&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fantastic!&lt;/p&gt;

&lt;p&gt;Everything loads as expected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftteitswvih5xl0xf2qs1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftteitswvih5xl0xf2qs1.png" alt="Expected loading of resources without file extensions" width="800" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;So what do these imports look like, and what is the project structure?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F087m1s9j6hsh7ncsctam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F087m1s9j6hsh7ncsctam.png" alt="Project structure in VS Code" width="584" height="708"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;./web/index.html&lt;/code&gt; file I am loading my counter component without the file extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Index&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;my-counter&amp;gt;&amp;lt;/my-counter&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/components/counter"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And my counter component imports &lt;code&gt;index.mjs&lt;/code&gt; from &lt;code&gt;./web/vendor/Shade/index.mjs&lt;/code&gt;. I'm using a &lt;code&gt;../&lt;/code&gt; to test that relative imports are really working.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&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;../vendor/Shade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&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;css&lt;/span&gt;&lt;span class="s2"&gt;`
        h1 {
            color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
        }
        ...
    `&lt;/span&gt;

    &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&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;html&lt;/span&gt;&lt;span class="s2"&gt;`
        &amp;lt;div&amp;gt;
            &amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h1&amp;gt;
            ...
        &amp;lt;/div&amp;gt;
    `&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nc"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyCounter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;css.mjs&lt;/code&gt; and &lt;code&gt;html.mjs&lt;/code&gt; are exported from &lt;code&gt;./web/vendor/Shade/index.mjs&lt;/code&gt; via the &lt;code&gt;lib&lt;/code&gt; directory. Eg:   &lt;code&gt;./web/vendor/Shade/lib/[html,css].mjs&lt;/code&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;html&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/html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;css&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/css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;shade&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/shade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;shade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try It!
&lt;/h2&gt;

&lt;p&gt;Check out Part 2 of the code for yourself. Download it from GitHub and play around with the imports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Shade-JS/ShadeJS/tree/part-2" rel="noopener noreferrer"&gt;https://github.com/Shade-JS/ShadeJS/tree/part-2&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Shade-JS/ShadeJS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ShadeJS
git checkout part-2
node run server/server.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do you think?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjf44kr7wkwmfaauxmms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjf44kr7wkwmfaauxmms.png" alt="ShadeJS GitHub Page" width="800" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>ShadeJS 🌴 Part 1 — Burn It All Down! 🔥</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Fri, 15 Dec 2023 03:07:22 +0000</pubDate>
      <link>https://forem.com/f1lt3r/build-a-spa-framework-1-4jld</link>
      <guid>https://forem.com/f1lt3r/build-a-spa-framework-1-4jld</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is &lt;strong&gt;Part 1&lt;/strong&gt; of the series: &lt;strong&gt;Build Your Own SPA Framework with Modular JavaScript, NodeJS and Closed-Shadow Web Components&lt;/strong&gt;.&lt;br&gt;
Part 1  |  &lt;a href="https://dev.to/f1lt3r/shadejs-part-2-the-magic-http-server-3467"&gt;Part 2&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Hi, I'm Al.&lt;/p&gt;

&lt;p&gt;And I've decided to make a modern SPA framework that DOESN'T SUCK! 🥳&lt;/p&gt;

&lt;p&gt;Why? Because I don't like build systems and code bundlers. Because I don't like 512 terrorbytes of bloatware in my node_modules folder. Because I'm fed up with transpilers, and code-wigglers, and domain-magic fizz-bunglers.&lt;/p&gt;

&lt;p&gt;I'm going to burn it all down. &lt;/p&gt;

&lt;p&gt;I just like clean, simple code that doesn't try to be too much.&lt;/p&gt;

&lt;p&gt;I'll be opinionated – So my code doesn't have to be.&lt;/p&gt;

&lt;p&gt;Why would I want to spend precious cycles fixing broken build systems when I can just press SHIP? Why should I be micromanaging my minifier for a microseconds gain, when the only code I need to load is that what is on the screen right now? Who cares about types anyway when you can build your whole app with only strings? Why smash my head against a strongly typed API schema just so I can get intellisense?&lt;/p&gt;

&lt;p&gt;REALLY?!&lt;br&gt;
Does it make any-sense, to you?&lt;/p&gt;

&lt;p&gt;It's too much I tell you.&lt;br&gt;
&lt;strong&gt;TOO MUCH!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why can't I just compose deep in flow-state, rapidly swinging out components into production like Chuck Norris?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bmdlx580qhnecg3d7j7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bmdlx580qhnecg3d7j7.gif" alt="Chuck Norris catching some shade and returning it to sender" width="285" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can – I tell you. &lt;strong&gt;AND I WILL!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No, seriously.&lt;/p&gt;

&lt;p&gt;I want to build the most framework-less framework of frameworks, The little codebase that couldn't get in your way if it tried.&lt;/p&gt;

&lt;p&gt;But how?&lt;/p&gt;
&lt;h1&gt;
  
  
  How
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;What I will use?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Web Components&lt;/li&gt;
&lt;li&gt;Modular JavaScript&lt;/li&gt;
&lt;li&gt;NodeJS&lt;/li&gt;
&lt;li&gt;JavaScript Runtime Interpreter&lt;/li&gt;
&lt;li&gt;JavaScript CSS Parsing Engine&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What will features be?&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;.mjs-Aware HTTP Server&lt;/li&gt;
&lt;li&gt;Build-less Deployments&lt;/li&gt;
&lt;li&gt;LIVE Fragments triggering tiny DOM updates&lt;/li&gt;
&lt;li&gt;Runs under a tight Content Security Policy with no &lt;code&gt;unsafe-eval&lt;/code&gt; or &lt;code&gt;unsafe-inline&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Built in Lazy Loading &lt;/li&gt;
&lt;li&gt;Two Way Data Binding&lt;/li&gt;
&lt;li&gt;SPA Integration w/ Browser History&lt;/li&gt;
&lt;li&gt;Modular CSS Templates&lt;/li&gt;
&lt;li&gt;Hot Module Swapping (HMR)&lt;/li&gt;
&lt;li&gt;Storybooks Integration&lt;/li&gt;
&lt;li&gt;Unit &amp;amp; End-to-End test Integration&lt;/li&gt;
&lt;li&gt;Recommended VS Code Integrations &lt;/li&gt;
&lt;li&gt;Traditional Package Bundling (Maybe)&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  Choose a Name
&lt;/h1&gt;

&lt;p&gt;Because I want to take advantage of the performance improvements and tighter security of Closed Shadow Web Components, I'm looking for a name that has something-to-do with "shadows".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbip8t3idtoiliuezu1zr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbip8t3idtoiliuezu1zr.jpg" alt="Image description" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like the idea of sitting in the cool shade of a palm tree on hot, sunny day, and that gives me some great ideas for a logo; so I'm thinking "ShadeJS"?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domains Available? "YES"&lt;/li&gt;
&lt;li&gt;NPM Names Available? "YES"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a done deal.  🤝&lt;/p&gt;
&lt;h1&gt;
  
  
  Design The Components
&lt;/h1&gt;

&lt;p&gt;I want to use Web Components as the base for this framework. So I am going to start by designing what a simple component might look like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's an example of a simple counter component:&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&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;/vendor/Shade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&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;css&lt;/span&gt;&lt;span class="s2"&gt;`
        h1 {
            color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
        }
        p {
            border: 1px dotted black;
            padding: 1rem;
        }
    `&lt;/span&gt;

    &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&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;html&lt;/span&gt;&lt;span class="s2"&gt;`
        &amp;lt;div&amp;gt;
            &amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h1&amp;gt;
            &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
            &amp;lt;button @click="subtract(1)"&amp;gt;Subtract 1&amp;lt;/button&amp;gt;
            &amp;lt;button @click="add(1 + 1)"&amp;gt;Add 2&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
    `&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nc"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyCounter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having the &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;template&lt;/code&gt; as callback functions give me some nice control over the code - control that I can abstract away.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pass state into the callback for &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;template&lt;/code&gt; to: 

&lt;ul&gt;
&lt;li&gt;Update CSS values like color, eg: &lt;code&gt;color: ${count &amp;gt;= 8 ? 'red' : 'green'}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Show / Hide portions of the template&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Evaluate &amp;amp; run code in the template, eg: &lt;code&gt;@click="add(1 + 1)&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Map arrays to render lists with HTML&lt;/li&gt;

&lt;li&gt;Stringify the &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;template&lt;/code&gt; functions to read the temple literal variable names, and update state when mutations happen.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Going Private
&lt;/h2&gt;

&lt;p&gt;What about private functions? Sometimes need the code to be invisible and untouchable from the outside. So lets think about what that might look like.&lt;/p&gt;

&lt;p&gt;Here is a method I could use for private components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&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;/vendor/Shade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;style&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="nx"&gt;css&lt;/span&gt;&lt;span class="s2"&gt;`
        h1 {
            color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
        }

        p {
            border: 1px dotted black;
            padding: 1rem;
        }
    `&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;template&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
        &amp;lt;div&amp;gt;
            &amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h1&amp;gt;
            &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
            &amp;lt;button @click="#subtract(1)"&amp;gt;Subtract 1&amp;lt;/button&amp;gt;
            &amp;lt;button @click="#add(1 + 1)"&amp;gt;Add 2&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
    `&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nc"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#add&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#subtract&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;subtract&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="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyCounter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can simplify this with a more functional component. Rather than using private members on a class, we can just pass functions and values without any reference to the outer scope.&lt;/p&gt;

&lt;p&gt;Here is an example:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&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;/vendor/Shade&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;count&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;css&lt;/span&gt;&lt;span class="s2"&gt;`
    h1 {
        color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
    }

    p {
        border: 1px dotted black;
        padding: 1rem;
    }
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&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;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
        &amp;lt;button @click="#subtract(1)"&amp;gt;Subtract 1&amp;lt;/button&amp;gt;
        &amp;lt;button @click="#add(1 + 1)"&amp;gt;Add 2&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
`&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;amount&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;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;amount&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;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;count&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCounter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nc"&gt;Shade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&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;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;subtract&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="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyCounter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;So I think I have a solid start on what I want from this framework, and what the developer experience is that I'm aiming for.&lt;/p&gt;

&lt;p&gt;Will it be the fastest framework in the wild?&lt;br&gt;
&lt;strong&gt;What is "fast"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Will it be the funnest developer experience out there?&lt;br&gt;
&lt;strong&gt;You betcha!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whatever happens, it will be a great way to learn some new tricks. And maybe you would like to learn them with me.&lt;/p&gt;

&lt;p&gt;What do you think? &lt;strong&gt;Should I go for it?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>framework</category>
      <category>spa</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Find File by Name w/ Linux CLI</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Thu, 29 Jun 2023 03:22:37 +0000</pubDate>
      <link>https://forem.com/f1lt3r/find-file-by-name-linux-cli-4pop</link>
      <guid>https://forem.com/f1lt3r/find-file-by-name-linux-cli-4pop</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"foo*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>find</category>
      <category>file</category>
      <category>linux</category>
      <category>cli</category>
    </item>
    <item>
      <title>Batch Convert MP3 to MP4</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Thu, 29 Jun 2023 03:04:18 +0000</pubDate>
      <link>https://forem.com/f1lt3r/batch-convert-mp3-to-mp4-1b</link>
      <guid>https://forem.com/f1lt3r/batch-convert-mp3-to-mp4-1b</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.mp4&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&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;i&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.mp3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>mp3</category>
      <category>mp4</category>
      <category>ffmpeg</category>
      <category>batch</category>
    </item>
    <item>
      <title>TypeScript?.. or JavaScript?</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Wed, 22 Jul 2020 07:36:05 +0000</pubDate>
      <link>https://forem.com/f1lt3r/typescript-or-javascript-8g2</link>
      <guid>https://forem.com/f1lt3r/typescript-or-javascript-8g2</guid>
      <description>&lt;p&gt;JavaScript! Why?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Better composability&lt;/li&gt;
&lt;li&gt;Faster development&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Type Safety Bugs
&lt;/h3&gt;

&lt;p&gt;I spend about 1% of my time dealing with types and type related bugs in JavaScript. To be fair, I use Prettier, ESLint, &amp;amp; BDD with VS Code, so most type safety bugs get knocked down before production anyway.&lt;/p&gt;

&lt;p&gt;Eric Elliot has a good post on this called, &lt;a href="https://medium.com/javascript-scene/the-typescript-tax-132ff4cb175b"&gt;The TypeScript Tax&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript is JavaScript's Aircraft Carrier
&lt;/h3&gt;

&lt;p&gt;To draw an analogy, JavaScript is a jump-jet and TypeScript is an aircraft carrier; And even though TypeScript is safe, it's still not safe enough to run a nuclear power plant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classes
&lt;/h3&gt;

&lt;p&gt;TypeScript's classes don't get me excited, because I don't use classes. I prefer JavaScript object composition.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enclosed Pure Object Composition
&lt;/h4&gt;

&lt;p&gt;I like to use Enclosed Pure Object Composition in place of Object Oriented Programming. Conceptually, the mental model is exactly the same, but with the added powers that first-class functions absorb in the Web's event based architecture. Everything I need from OOP can be done with plain JavaScript. No prototypes. No classes necessary.&lt;/p&gt;

&lt;p&gt;For example: here is the Enclosed Object equivalent of a Class:&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="c1"&gt;// Counter.mjs&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;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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="na"&gt;add&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;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;count&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Counter&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="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of object composition is easier to reason about. The &lt;a href="https://github.com/F1LT3R/js-oop-perf"&gt;memory footprint and CPU load of Object Composition&lt;/a&gt; is identical to Classes and Prototypes.&lt;/p&gt;

&lt;p&gt;Let's compose...&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="c1"&gt;// Counters.mjs&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;Counter&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;./Counter.mjs&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;Counters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;counters&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="na"&gt;add&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;counter&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;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;counter&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;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Counters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Counter&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="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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="nx"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [ 1, 2 ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Extensible Object Composition
&lt;/h3&gt;

&lt;p&gt;We can make our pattern more extensible. Here is a similar object composition, allowing for the use of JavaScript's &lt;code&gt;this&lt;/code&gt; keyword.&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="c1"&gt;// Employee.mjs&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;methods&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="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productivity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&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="s2"&gt;`I'm &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.
       I produced &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; units.`&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;worker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;productivity&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="na"&gt;product&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="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="p"&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;al&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Al&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// I'm Al, a worker. I produced 2 units.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's extend...&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="c1"&gt;// Manager.mjs&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;Employee&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;./Employee.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accept&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="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;productivity&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;productivity&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;al&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Al&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&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;promotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;manager&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;productivity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promotion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// I'm Al, a manager. I produced 1 units.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript's &lt;code&gt;this&lt;/code&gt; keyword is unnecessary. The same result can be achieved by passing the employee's state to the scope of the employee's methods.&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="c1"&gt;// Employee.mjs&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;work&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;work&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productivity&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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;employee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;worker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;productivity&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="na"&gt;product&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="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;work&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employee&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;al&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Al&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;work&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="nx"&gt;al&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Anti-Fragile
&lt;/h3&gt;

&lt;p&gt;Object composition in Vanilla JavaScript is anti-fragile. I don't have to keep changing my code when the language's class API surface shifts. I don't have to get things working again when packages in TypeScript's Node ecosystem deliver breaking changes, in exchange for fancier features or security enhancements. (This is not an anti-security statement).&lt;/p&gt;

&lt;h4&gt;
  
  
  Keep The Web Simple
&lt;/h4&gt;

&lt;p&gt;I often wonder how many frontend engineers learn frameworks, libraries and supersets, yet never realize the awesome power of modern JavaScript. &lt;/p&gt;

&lt;p&gt;I love writing pure, enclosed objects, wrapped in the lexical scopes of first class functions, all the way down; There's Very little magic, and a whole lot of beauty.&lt;/p&gt;

&lt;p&gt;If you want learn more about the inner workings of the code patterns above, read Kyle Simpson's excellent book series called, &lt;a href="https://github.com/getify/You-Dont-Know-JS"&gt;You Don't Know JS (Yet)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following three books are particularly helpful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/dp/B08634PZ3N?tag=duckduckgo-brave-20&amp;amp;linkCode=osi&amp;amp;th=1&amp;amp;psc=1"&gt;Scopes and Closures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/You-Dont-Know-JS-Prototypes/dp/1491904151/ref=pd_sbs_14_4/142-5566885-7736938?_encoding=UTF8&amp;amp;pd_rd_i=1491904151&amp;amp;pd_rd_r=f28c61fb-1557-47f9-9aed-e29bdbac1b82&amp;amp;pd_rd_w=f7qyZ&amp;amp;pd_rd_wg=wwrV8&amp;amp;pf_rd_p=bdc67ba8-ab69-42ee-b8d8-8f5336b36a83&amp;amp;pf_rd_r=XJ882256VAPZ0WA58CE5&amp;amp;psc=1&amp;amp;refRID=XJ882256VAPZ0WA58CE5"&gt;This and Object Prototypes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Kyle-Simpson/dp/1491904240/ref=sr_1_3?dchild=1&amp;amp;keywords=you+dont+know+javascript&amp;amp;qid=1595438516&amp;amp;s=digital-text&amp;amp;sr=1-3-catcorr"&gt;ES6 &amp;amp; Beyond&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_EuHfLav--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images-na.ssl-images-amazon.com/images/I/51llKt2oJEL._SX333_BO1%2C204%2C203%2C200_.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_EuHfLav--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images-na.ssl-images-amazon.com/images/I/51llKt2oJEL._SX333_BO1%2C204%2C203%2C200_.jpg" alt="You Don't Know JavaScript - Book Set" width="335" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opinion</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Down Boy! (Kill processes by Port)</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Fri, 10 May 2019 11:40:12 +0000</pubDate>
      <link>https://forem.com/f1lt3r/down-boy-kill-by-port-1cmb</link>
      <guid>https://forem.com/f1lt3r/down-boy-kill-by-port-1cmb</guid>
      <description>&lt;p&gt;Need to kill processes by port? Try this...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmwjl1xsp7e57t311up5k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmwjl1xsp7e57t311up5k.jpg" alt="Cute dog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Save this bash script as &lt;code&gt;downboy&lt;/code&gt; to your bin directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;PORT &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; :&lt;span class="nv"&gt;$PORT&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'FNR ==2 {print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"kill -9 &lt;/span&gt;&lt;span class="nv"&gt;$PID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nt"&gt;-9&lt;/span&gt; &lt;span class="nv"&gt;$PID&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make &lt;code&gt;downboy&lt;/code&gt; executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +X ./downboy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now you can easily close any number of processes by their port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;downboy 80 8080 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bye-bye.&lt;/p&gt;

</description>
      <category>kill</category>
      <category>port</category>
      <category>pid</category>
      <category>process</category>
    </item>
    <item>
      <title>Agile Insight: Time = Complexity</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Mon, 06 May 2019 05:17:31 +0000</pubDate>
      <link>https://forem.com/f1lt3r/agile-insight-time-complexity-fgh</link>
      <guid>https://forem.com/f1lt3r/agile-insight-time-complexity-fgh</guid>
      <description>&lt;p&gt;Many Agile teams use Story Points as the measure for both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The length in time to complete a task&lt;/li&gt;
&lt;li&gt;The complexity of engineering a task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is that over time, a team will normalize on some fuzzy, but shared idea of what a Story Point represents. That fuzzy, but shared idea will evolve over time. A task that takes three Story Points today may only take one Story Point in the future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zZmZ8lHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dmfmrvmeitw7j9bpked6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zZmZ8lHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dmfmrvmeitw7j9bpked6.jpg" alt="clock"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inconsistent Measures
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Each team is different, changing over time&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One team’s idea of a Story Point does not necessarily match another teams idea of a Story Point. This is a problem for the organization because variability in measures makes forecasting more unreliable. Forecasting is already unreliable enough.&lt;/p&gt;

&lt;p&gt;Businesses place a high value on knowing how long it takes deliver software, and though it is not possible to know how long it really takes, the business can not act until it has counted the cost. Even though the cost is wrong, it’s closer than it was when you didn’t guess.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So why make it harder for the organization by using an inconsistent measure?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Insight
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Time &lt;strong&gt;already is&lt;/strong&gt; a consistent measure of Complexity&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Complex tasks take longer than simple tasks. Simple tasks can be broken down more easily than complex tasks, therefore they can be shorter. Breaking complex tasks down is hard, and takes time.&lt;/p&gt;

&lt;p&gt;If you have a simple task that takes a day, and a complex task that takes a day, both tasks add the same value to your average velocity. &lt;/p&gt;

&lt;p&gt;So what does it mean that one task is simple and one is complex?&lt;/p&gt;

&lt;p&gt;It only means time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dimensions Not Leveraged
&lt;/h2&gt;

&lt;p&gt;Lets examine our problem space from easiest to estimate, to hardest to estimate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simple tasks that are short&lt;/li&gt;
&lt;li&gt;Simple tasks that are long&lt;/li&gt;
&lt;li&gt;Complex tasks that are short&lt;/li&gt;
&lt;li&gt;Complex tasks that are long&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This problem space has two axis: Complexity and Time, yet both are overloaded into the single measure of the Story Point. If we really wanted to capture time and complexity as values we could leverage, we would be better off using two distinct variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Losing The Dimension of Complexity
&lt;/h2&gt;

&lt;p&gt;So what are we saying when we map Complexity and Time together?&lt;/p&gt;

&lt;p&gt;Let &lt;code&gt;c = complexity&lt;/code&gt;, &lt;code&gt;t = time&lt;/code&gt; and &lt;code&gt;sp = Story Points&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simple-Short: &lt;code&gt;1c + 1t = 2sp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Simple-Long: &lt;code&gt;1c + 2t = 3sp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Complex-Short: &lt;code&gt;2c + 1t = 3sp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Complex-Long: &lt;code&gt;3c + 3t = 6sp&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the example above, the Simple-Long task and the Complex-Short task are both estimated to be &lt;code&gt;3sp&lt;/code&gt;. In this case, the engineers are estimating that both tasks will take a similar amount of effort. &lt;/p&gt;

&lt;p&gt;Then some haunted soul is forced to calculate the average velocity of the team (story points per sprint), and use that average to gate how many stories can fit into the next sprint. &lt;/p&gt;

&lt;p&gt;The multidimensional Story Point has now been boiled back down to the linear dimension of time.&lt;/p&gt;

&lt;p&gt;You can add as many axis to your Story Points as you want, but you’re only leveraging one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Real, Use Days
&lt;/h2&gt;

&lt;p&gt;The estimate for our Complex-Short task might be justified like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I think this should task should be quick, probably about a day, but there’s a couple of areas I’m not so sure about - it could get a little complex, so let’s say three Story Points.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That &lt;code&gt;3sp&lt;/code&gt; will be used to measure against points from another sprint, which maps to a value of time. So what you’re actually saying is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“That Short-Complex story will likely take me &lt;em&gt;three days&lt;/em&gt;.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… even though you did not provide your estimate in days.&lt;/p&gt;

&lt;h1&gt;
  
  
  How Many Days?
&lt;/h1&gt;

&lt;p&gt;What if we start asking this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“&lt;strong&gt;How many days&lt;/strong&gt; do you think this story would take?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then you might answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“About two or three days, so let’s say three to be safe.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we have a measure of three days, or &lt;code&gt;3d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because we are flattening Complexity down to Time anyway, we may as well just estimate in days. &lt;/p&gt;

&lt;p&gt;No Agile magic required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day Points - A Standard Measure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A day means a day, for any team&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;While it’s true that one team may be able to get more done in a day than another, at least everyone can use a standard measure to estimate future work: one day.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;1d = one day's work&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;A day means a day, for any time&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One day still means “one day”, in two years. The same cannot be said for Story Points, they only mean something to a specific team at a specific time.&lt;/p&gt;

&lt;p&gt;I recommend just using a point for a day.&lt;/p&gt;

&lt;p&gt;It easier, and less pretentious.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Be careful using Day Points. Agile is a religion, and people are scared of decimals.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>agile</category>
      <category>scrum</category>
      <category>complexity</category>
      <category>storypoints</category>
    </item>
    <item>
      <title>Compact or Verbose Codestyle?</title>
      <dc:creator>F1LT3R </dc:creator>
      <pubDate>Sun, 25 Nov 2018 17:51:41 +0000</pubDate>
      <link>https://forem.com/f1lt3r/compact-or-verbose-codestyle-30dd</link>
      <guid>https://forem.com/f1lt3r/compact-or-verbose-codestyle-30dd</guid>
      <description>&lt;p&gt;Which code style do you prefer and why?&lt;/p&gt;

&lt;h2&gt;
  
  
  Compact
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nb"&gt;Reflect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
        &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Key "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" not found in window.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;store&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Verbose
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&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="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Reflect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Key "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" not found in window.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;store&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="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;key&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;dataObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonStr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataObj&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;



</description>
      <category>programming</category>
      <category>codestyle</category>
      <category>maintenance</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
