<?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>DEV Community: Nathan Blaylock</title>
    <description>The latest articles on DEV Community by Nathan Blaylock (@ngblaylock).</description>
    <link>https://dev.to/ngblaylock</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%2F675978%2F23f3a13b-7f60-4eba-a36d-a708a2d58490.jpg</url>
      <title>DEV Community: Nathan Blaylock</title>
      <link>https://dev.to/ngblaylock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ngblaylock"/>
    <language>en</language>
    <item>
      <title>Bootstrap 5 Responsive Mode Buttons</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Sun, 04 Aug 2024 04:01:14 +0000</pubDate>
      <link>https://dev.to/ngblaylock/bootstrap-5-responsive-mode-buttons-2kfi</link>
      <guid>https://dev.to/ngblaylock/bootstrap-5-responsive-mode-buttons-2kfi</guid>
      <description>&lt;p&gt;&lt;strong&gt;This only applies to Bootstrap 5.3 and later using dark mode.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've been exploring dark mode a little more lately for some personal projects using Bootstrap 5. One thing that I find quite annoying is using Bootstrap 5's dark outline button in dark mode. This looks just fine in light mode, but when you switch to dark mode it becomes invisible. How do you get around that?&lt;/p&gt;

&lt;p&gt;It's actually quite easy. I call these "Contrast Buttons". These use the default body and background color to present the button with better contrast: dark in light mode and light in dark mode.&lt;/p&gt;

&lt;p&gt;All you have to do is plug in this CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn-outline-contrast&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-bs-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;light&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.btn-outline-contrast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-focus-shadow-rgb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;41&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-gradient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-bs-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.btn-outline-contrast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-focus-shadow-rgb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;222&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;226&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;230&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-gradient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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;This follows pretty closely with how Bootstrap handles &lt;code&gt;.btn.btn-outline-dark&lt;/code&gt; but changes some colors specifically for dark mode.&lt;/p&gt;

&lt;p&gt;Then just add &lt;code&gt;&amp;lt;button class="btn btn-outline-contrast"&amp;gt;Button&amp;lt;/button&amp;gt;&lt;/code&gt; to your HTML, and you should have the appropriate contrast button depending on the selected mode.&lt;/p&gt;

&lt;p&gt;This is what you should see:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  I Want More
&lt;/h2&gt;

&lt;p&gt;Having the contrast button work for outline buttons is great, but I would also like a regular contrast button. This is all you need in both cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn-contrast&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-bs-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;light&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.btn-contrast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1c1f23&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1a1e21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-focus-shadow-rgb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;66&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;73&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1a1e21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#191c1f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.btn-outline-contrast&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-bs-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;light&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.btn-outline-contrast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-focus-shadow-rgb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;37&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;41&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#212529&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-gradient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-bs-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.btn-contrast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e3e6ea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e1e5e9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-focus-shadow-rgb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;189&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;196&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e5e8eb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e1e5e9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-bs-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;dark&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="nc"&gt;.btn-outline-contrast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-hover-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-focus-shadow-rgb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;222&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;226&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;230&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-active-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-btn-disabled-border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#dee2e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--bs-gradient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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;Here is what that looks like in both light and dark mode.&lt;/p&gt;

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

&lt;p&gt;I hope this helps anyone looking for a good solution to this missing feature.&lt;/p&gt;

</description>
      <category>css</category>
      <category>bootstrap</category>
    </item>
    <item>
      <title>Eleventy/Figma Plugin Template</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Mon, 12 Jun 2023 20:24:40 +0000</pubDate>
      <link>https://dev.to/ngblaylock/eleventyfigma-plugin-template-4nhn</link>
      <guid>https://dev.to/ngblaylock/eleventyfigma-plugin-template-4nhn</guid>
      <description>&lt;p&gt;I recently developed a pretty neat plugin for Figma called &lt;a href="https://www.figma.com/community/plugin/1098444899707858859/Placeholdate"&gt;Placeholdate&lt;/a&gt; which solved a problem I was having with other plugins. I use plugins like "Faker" and "Figma Data Faker" but their date outputs were not formatted the way I wanted. So, I made my own plugin to generate random dates and allow me to output whatever date format I wanted. It was very helpful for me, as well as 2k+ users. &lt;/p&gt;

&lt;p&gt;As I was developing that plugin I found that managing all of my code in one &lt;code&gt;.html&lt;/code&gt; file was getting rather difficult. So I decided to make my own quick Node script that would allow me to compile all of my separate &lt;code&gt;.js&lt;/code&gt;, &lt;code&gt;.scss&lt;/code&gt;, and&lt;code&gt;.html&lt;/code&gt; files into a single file. It was a pretty hacky script to be honest, but it worked.&lt;/p&gt;

&lt;p&gt;I recently decided to try out a new plugin and I started using that same script from my Placeholdate plugin, but I wasn't super happy with it. I looked at other options such as Webpack (&lt;a href="https://www.figma.com/plugin-docs/libraries-and-bundling/#bundling-with-webpack"&gt;Figma's suggestion&lt;/a&gt;) and &lt;a href="https://github.com/thomas-lowry/figsvelte"&gt;Figsvelte&lt;/a&gt;, but I wanted something familiar with a simple setup. I decided to try out &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have used Eleventy before on multiple projects, but I never tried to do things like inlining CSS from a Sass file, or just inlining text from any file type. After some research I wrote a slick filter that could pull code from a file and inject it in the HTML. The output of this Eleventy project is a single, minified HTML file with all scripts and style written inline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To get started, use the &lt;a href="https://github.com/ngblaylock/eleventy-figma-plugin-template"&gt;template from GitHub&lt;/a&gt;. In a terminal, navigate to this folder and run &lt;code&gt;npm install&lt;/code&gt;. This will install all of the Eleventy and Figma dependencies. &lt;/p&gt;

&lt;p&gt;Once that is done, you will need to get your own Figma plugin ID. In the &lt;code&gt;manifest.json&lt;/code&gt; file you will see an ID field with "###################". You will want to replace that number.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In Figma Desktop go to Plugins &amp;gt; Development &amp;gt; New Plugin. &lt;/li&gt;
&lt;li&gt;Add in a plugin name (whatever you want, it doesn't matter), then choose "Figma Design", then next.&lt;/li&gt;
&lt;li&gt;Choose "Custom UI". You will then be prompted to save the plugin somewhere. &lt;/li&gt;
&lt;li&gt;Open that folder that you saved and open the &lt;code&gt;manifest.json&lt;/code&gt; file and copy that ID. &lt;/li&gt;
&lt;li&gt;Paste that ID into this template.&lt;/li&gt;
&lt;li&gt;OPTIONAL: If you are new to developing plugins for Figma, you might want to read through that README.md file which has additional information not found here.&lt;/li&gt;
&lt;li&gt;You can delete that new plugin folder you just created. You don't need it anymore.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This project is set up to use &lt;code&gt;src&lt;/code&gt; as the input directory and &lt;code&gt;dist&lt;/code&gt; as the output directory. The &lt;code&gt;src&lt;/code&gt; directory will include &lt;code&gt;code.ts&lt;/code&gt; which is code for the Figma side of the plugin, and other files are handled by Eleventy. This setup uses Nunjucks, but you can use whatever other templating language Eleventy offers if you want. If you open &lt;code&gt;index.njk&lt;/code&gt; there will be some comments guiding you on how to use the template.&lt;/p&gt;

&lt;p&gt;To begin development, run &lt;code&gt;npm run dev&lt;/code&gt;. This will create &lt;code&gt;dist/index.html&lt;/code&gt; from the Eleventy project and &lt;code&gt;dist/code.ts&lt;/code&gt; from the &lt;code&gt;code.ts&lt;/code&gt; file. From here, you can go to Figma &amp;gt; Plugins &amp;gt; Development &amp;gt; Import Plugin from Manifest. Select this project manifest and you can start using the plugin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Inlining JS, CSS, and Sass
&lt;/h2&gt;

&lt;p&gt;The main limitation to developing plugins for Figma is that everything needs to be in one single &lt;code&gt;.html&lt;/code&gt; file. This means that all JavaScript and CSS needs to be used in a &lt;code&gt;&amp;lt;script&amp;gt;...&amp;lt;/script&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;style&amp;gt;...&amp;lt;/style&amp;gt;&lt;/code&gt; tag. You can manually write these, but this template provides a filter to extract that from a separate file and inline it in the output file. You can also use Sass which will automatically compile to CSS. Simply add a filter to your &lt;code&gt;.njk&lt;/code&gt; file where ever you want it inserted (see the example below). You can also pull code from &lt;code&gt;node_modules&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- Please note that these file paths are relative to the `.eleventy.js` config file. --&amp;gt;
{{ './src/style.scss' | inlineFromFile | safe }}
{{ './src/style.css' | inlineFromFile | safe }}
{{ './src/script.js' | inlineFromFile | safe }}
{{ './node_modules/alpinejs/dist/cdn.js' | inlineFromFile | safe }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding External Code (CDN)
&lt;/h2&gt;

&lt;p&gt;If you don't want to inline your code, but would rather use a CDN, you will need to modify the &lt;code&gt;manifest.json&lt;/code&gt; file to allow the domains. Check out the &lt;a href="https://www.figma.com/plugin-docs/manifest/#networkaccess"&gt;documentation&lt;/a&gt; for more details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"networkAccess"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowedDomains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"cdnjs.cloudflare.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Documentation Links
&lt;/h2&gt;

&lt;p&gt;For more information regarding development, check out the links below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.figma.com/plugin-docs/"&gt;Figma Plugin Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.11ty.dev/"&gt;Eleventy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>eleventy</category>
      <category>figma</category>
    </item>
    <item>
      <title>Extract Data from Google Sheets</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Fri, 25 Mar 2022 04:48:30 +0000</pubDate>
      <link>https://dev.to/ngblaylock/extract-data-from-google-sheets-13jn</link>
      <guid>https://dev.to/ngblaylock/extract-data-from-google-sheets-13jn</guid>
      <description>&lt;p&gt;As a JAMStack developer, I have often found a situation where all I need is a way to get data and display it on a website. There are a lot of options out there, like creating a database with an API, using serverless technology like Firebase, or many other options. But that often seems a little overkill. &lt;/p&gt;

&lt;p&gt;Sometimes, all I need is a spreadsheet as a read-only data source. Google Sheets is an appealing option because it is familiar to many people, is available as a web application, and makes storing and organizing data a breeze. Wouldn't it be nice to use this as a data source?&lt;/p&gt;

&lt;p&gt;One solution I have used to get Google Sheet data was &lt;a href="https://github.com/jsoma/tabletop"&gt;Tabletop.js&lt;/a&gt; which was written several years ago and no longer works. Other solutions out there cost money. Some seem a little questionable when you hand over your Google credentials allowing them access to your Google Drive. &lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing: Extract GSheet
&lt;/h2&gt;

&lt;p&gt;Since I wasn't happy with any of these solutions, I decided to write and publish my own library to extract data from a Google Sheet. &lt;/p&gt;

&lt;p&gt;Extract GSheet is a front-end JavaScript library that extracts your published Google Sheet data making it available as a JavaScript object. It can even pull data from multiple tabs within the same document! From there, you can display the content however you would like. Unlike many other libraries, this library does not require an API key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Take a look at the following CodePen to see how easy it is to extract data from &lt;a href="https://docs.google.com/spreadsheets/d/e/2PACX-1vTRI47Ifj6D_US-HpggfPwSGU1nBSz81IaQ3FL3eqqjr2m8ZIdr6ia9L_FqsJqYVeUI_A2SDjm25FjG/pubhtml"&gt;this published Google Sheet data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ngblaylock/embed/KKvGqvw?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Extract GSheet will pull out all text data in the table and convert it as needed. For example, "1" ⇒ 1, "TRUE" ⇒ true, and will convert checkboxes to a true/false value.&lt;/li&gt;
&lt;li&gt;It will use the first row in the sheet as the key for the key/value pairs.&lt;/li&gt;
&lt;li&gt;It will remove empty rows and columns to keep the data clean.&lt;/li&gt;
&lt;li&gt;If there is no column labeled &lt;code&gt;id&lt;/code&gt;, it will add an id for each non-empty row.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What This Won't Do
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Extract GSheet is intended to only read data from a Google Sheet. It cannot write data to a Google Sheet. If you need to update information on your website, you will need to edit the Google Sheet. Any changes on your Google Sheet should automatically publish once changed. However, some changes may take up to 5 minutes to reflect on your page.&lt;/li&gt;
&lt;li&gt;Extract GSheet relies on &lt;code&gt;DomParser&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt; which are not native to Node.js. Because of this, it will only work in a browser.&lt;/li&gt;
&lt;li&gt;Extract GSheet will not extract non-text items such as images, comments, and charts.&lt;/li&gt;
&lt;li&gt;It does not work in Internet Explorer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Documentation and Examples
&lt;/h2&gt;

&lt;p&gt;You should have a pretty good idea of how easy it is to implement based on the CodePen above, but if you still need additional help, you can find more information in the &lt;a href="https://ngblaylock.github.io/extract-gsheet/documentation/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also have examples of formatting data using different libraries and frameworks such as jQuery, Vue, React, and more. You can find those examples at &lt;a href="https://ngblaylock.github.io/extract-gsheet/"&gt;https://ngblaylock.github.io/extract-gsheet/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions?
&lt;/h2&gt;

&lt;p&gt;If you have questions, drop them in the comments here, or let me know on &lt;a href="https://github.com/ngblaylock/extract-gsheet"&gt;GitHub&lt;/a&gt;. I hope you find this useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ngblaylock.github.io/extract-gsheet/"&gt;Documentation and Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/extract-gsheet"&gt;extract-gsheet on NPM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codepen.io/ngblaylock/pen/KKvGqvw"&gt;CodePen Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>google</category>
      <category>spreadsheet</category>
      <category>jamstack</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How I Set Up a Project With Eleventy</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Sun, 15 Aug 2021 00:07:23 +0000</pubDate>
      <link>https://dev.to/ngblaylock/how-i-set-up-a-project-with-eleventy-31gc</link>
      <guid>https://dev.to/ngblaylock/how-i-set-up-a-project-with-eleventy-31gc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is a quick overview on my typical setup for an 11ty project. I really like how it is set up and want to share it with other people.&lt;/p&gt;

&lt;h2&gt;
  
  
  File Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── assets
│   ├── favicon.ico
│   └── ... (img, pdf, etc.)
├── dist
│   └── ... (output static files)
├── node_modules
│   └── ...
├── pages
│   ├── _data
│   │   └── global.js
│   ├── _includes
│   │   ├── _footer.njk
│   │   ├── _head.njk
│   │   └── _nav.njk
│   ├── _layouts
│   │   └── default.njk
│   ├── 404.njk
│   ├── index.njk
│   ├── pages.json
│   ├── uikit.njk
│   └── ...
├── styles
│   └── style.scss
├── .eleventy.js
├── package.json
├── package-lock.json
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Eleventy Config File (.eleventy.js)
&lt;/h2&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;pluginSass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eleventy-plugin-sass&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eleventyConfig&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="c1"&gt;// Copy our static assets to the output folder&lt;/span&gt;
  &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pluginSass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
  &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addPassthroughCopy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./&lt;/span&gt;&lt;span class="dl"&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="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_layouts&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  NPM Installs and Scripts
&lt;/h2&gt;

&lt;p&gt;Obviously, you need to install Eleventy. I use it as a dev dependency rather than loading it globally. &lt;/p&gt;

&lt;p&gt;I install &lt;code&gt;rimraf&lt;/code&gt; in order to clean my output directory everytime I build the site. By default, Eleventy won't clean out files in the output directory if you move them or delete them.&lt;/p&gt;

&lt;p&gt;I Use &lt;code&gt;cross-env&lt;/code&gt; to set environment variables (development or production). This is used in my global data so I can show or hide certain things depending on if I am in development mode or production. For example, I may use vue.js in development to use the browser dev tools, then use vue.min.js in production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev @11ty/eleventy rimraf cross-env eleventy-plugin-sass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use three scripts in my &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run clean &amp;amp;&amp;amp; cross-env ELEVENTY_ENV=dev npx @11ty/eleventy --serve --output=dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx rimraf ./dist ./dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run clean &amp;amp;&amp;amp; cross-env ELEVENTY_ENV=prod npx @11ty/eleventy"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Global Data
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;cross-env&lt;/code&gt; combined with the &lt;code&gt;package.json&lt;/code&gt; script you can set an environment variable and use it in your template file. For nunjuks, just use &lt;code&gt;{{global.env}}&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="c1"&gt;// ./pages/_data/global.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELEVENTY_ENV&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pages Global Data
&lt;/h2&gt;

&lt;p&gt;One of the things that I have found a lot of people want in Eleventy is to set a default layout for the project. In Eleventy's documentation, it says that you can add a &lt;code&gt;&amp;lt;directory&amp;gt;.json&lt;/code&gt; and it will use that data as the default data for every template page in that directory. The issue is in the root of the project you can't specify that. If you use a directory like &lt;code&gt;pages&lt;/code&gt; as your input directory, then you can set a &lt;code&gt;pages.json&lt;/code&gt; and use global data there. The most used one is the layout for me. Most all of my layouts should use "default". You can easily override these in the template front matter. Here is my example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"layout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default description for project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Default Project Title"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>jamstack</category>
      <category>eleventy</category>
    </item>
    <item>
      <title>My Favorite VS Code Extensions for JAMStack Development</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Wed, 11 Aug 2021 04:53:10 +0000</pubDate>
      <link>https://dev.to/ngblaylock/my-favorite-vs-code-extensions-for-jamstack-development-3lai</link>
      <guid>https://dev.to/ngblaylock/my-favorite-vs-code-extensions-for-jamstack-development-3lai</guid>
      <description>&lt;p&gt;I wanted to share some of my favorite extensions as a front-end developer. There are thousands of extensions out there, however, some of them are more useful than others. So here is my (ever growing) list in alphabetical order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alphabetical Sorter (Ugur Erdal)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T5i3ugY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qi9ay02dtxz0jnam1o4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T5i3ugY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qi9ay02dtxz0jnam1o4u.png" alt="image" width="72" height="72"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Speaking of alphabetical order, this is a nifty extension that will quickly sort a list in alphabetical order. I find this useful with &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; where you have multiple items that need to be sorted. Just write them out, and run the extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto Rename Tag (Jun Han)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RBGWsTHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adbh3puockao8mu3f2lz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RBGWsTHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adbh3puockao8mu3f2lz.png" alt="image" width="106" height="72"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I hate going in and changing the opening tag, and then the closing tag. Once I installed this extension, there was no going back.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But hey, VS Code has this built in now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, I know. But I have a hard time getting it to work with &lt;code&gt;.vue&lt;/code&gt; files. It is still nice to have or know about if the built in functionality doesn't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autoprefixer ( mrmlnc)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gOYeLVI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8z5modlv2gt8bk1bj49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gOYeLVI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8z5modlv2gt8bk1bj49.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't use this as much anymore since I use Sass and my setup automatically autoprefixes, but it is still nice if you are just writing CSS and want to add vender prefixes automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Material Theme (Equinusocio)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zhNEcUU_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fudvtdodf01tgt62q9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zhNEcUU_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fudvtdodf01tgt62q9l.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There isn't really anything wrong with VS Code's default interface styles, but I really like using this one. My favorite is "Material Theme High Contrast"&lt;/p&gt;

&lt;h2&gt;
  
  
  FiraCode w/ Ligatures
&lt;/h2&gt;

&lt;p&gt;This isn't an extension, but it is some customization to use a different font and use ligatures in VS Code. Check out the &lt;a href="https://github.com/tonsky/FiraCode"&gt;documentation&lt;/a&gt; for details on how to install it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Git History (Don Jayamanne)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D16uxysq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gxg98cmns8772djeuu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D16uxysq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gxg98cmns8772djeuu9.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Version control is awesome, but as a front end developer, I don't just want to see the code from a point in time, I want to see what it looked like. With this extension you can do a hard reset (&lt;strong&gt;make sure that your latest changes are committed to a remote repository&lt;/strong&gt;). Then you can run the site like it was at that point. When you are done, you just pull the latest change from your remote repository, and you are back to where you were.&lt;/p&gt;

&lt;h2&gt;
  
  
  Highlight Matching Tag (vincaslt)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--opXTSZEx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hc0smkgbpsl3n5vommw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--opXTSZEx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0hc0smkgbpsl3n5vommw.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This does exactly what it says, if your cursor is on &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; it will find the matching &lt;code&gt;&amp;lt;/div&amp;gt;&lt;/code&gt; and highlight it. This is another one that VS Code has some built in functionality for, but I just like how this one looks.&lt;/p&gt;

&lt;h2&gt;
  
  
  html-entities (christopherstyles)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f3c2YPyH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9azhxkp5hsbhgy1fx87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f3c2YPyH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9azhxkp5hsbhgy1fx87.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is no bigger pain than writing &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; content, to find out that everything you wrote in it was rendered as HTML on your page. With this extension, you can type it out, highlight your code, then run this extension. Now all your &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt; (and others) are translated into HTML entities; &lt;code&gt;&amp;amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;amp;gt;&lt;/code&gt; respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Sass Compiler (Ritwick Dey)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I-KtSy_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuefgg42tcycfwk673kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I-KtSy_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuefgg42tcycfwk673kj.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am fortunately finding alternatives for this, but in some projects it is so helpful to just have a free Sass compiler. You hit a button in the bottom of the window, and all your Sass files in your project are rendered (except the ones prefixed with &lt;code&gt;_&lt;/code&gt;). If your project doesn't have some sort of sass compiler built in, give this a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Server (Ritwick Dey)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NhCHS_vI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5j45x7p7hzuumibkhsy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NhCHS_vI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5j45x7p7hzuumibkhsy.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will turn your project into a hot-reloaded server. As long as you have an HTML page with a &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; it will open the page in a new tab and refresh it whenever you change a file. One thing I like about it is if you have a project that doesn't have an HTML file, but something else you want to hot reload, you can combine this with the Chrome extension (made by the same person, and named the same thing), and you can connect your two sites so when you make updates to a file, it tells another tab with a specific web address to refresh.&lt;/p&gt;

&lt;p&gt;This extension is limited For example, you can't use a subdirectory as the root. You can look into Five Server (Yannick) which is maintained and gives you different options. I haven't tried it yet, but it looks promising.&lt;/p&gt;

&lt;h2&gt;
  
  
  Markdown All in One (Yu Zhang)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_6zUsm-o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2w1fxjzwv0vgrdj1w5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_6zUsm-o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2w1fxjzwv0vgrdj1w5u.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This helps me keep my markdown files formatted well. Also, it gives you a live preview of it, which I don't use much. The formatting is really what I use it for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Material Icon Theme (Philipp Kief)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KxHbQf0A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0dxd9u7nccw54v4zfv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KxHbQf0A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0dxd9u7nccw54v4zfv6.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default VS Code icons are ugly. Use this theme and they look much better. I especially don't like the default Vue icon. It doesn't have the right colors. Maybe it was a Vue 1.0 logo?&lt;/p&gt;

&lt;h2&gt;
  
  
  Nunjucks for VS Code (ExE Boss)
&lt;/h2&gt;

&lt;p&gt;This isn't perfect, but it is the best Nunjucks extension in my opinion (I mostly use it with Eleventy). It doesn't have code snippets, or auto formatting, so you have to configure that a different way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path Autocomplete (Mihai Vilcu)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kA2IwGpY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxp4zhbzhioxf2htsx0d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kA2IwGpY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxp4zhbzhioxf2htsx0d.png" alt="image" width="123" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In most of my projects, the files I am trying to link to are in something like a &lt;code&gt;pages&lt;/code&gt; directory. So my &lt;code&gt;about.html&lt;/code&gt; file would be in &lt;code&gt;/pages/about.html&lt;/code&gt; in my project, but the actual link should be to &lt;code&gt;/about.html&lt;/code&gt;. When you try to link to the about file the intellisense doesn't pick it up because it is looking at the root of the project. With this extension, you can tell intellisense to also look in the &lt;code&gt;pages&lt;/code&gt; directory. Typing &lt;code&gt;/abo&lt;/code&gt; will pop up &lt;code&gt;/about.html&lt;/code&gt; (you do need to configure that functionality).&lt;/p&gt;

&lt;h2&gt;
  
  
  Prettier (Prettier)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v37x4Imw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pcd20d4td3455cdoshcl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v37x4Imw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pcd20d4td3455cdoshcl.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This if my favorite formatter. You can configure a lot of things in it, and even tell it to format one file type as another (like Nunjucks as HTML).&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Manager (Alessandro Fragnani)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cJkGNwND--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/arxj6rxefjvcgzq9chqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cJkGNwND--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/arxj6rxefjvcgzq9chqh.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Workspaces are fine, but I prefer to keep my projects managed with this extension. Think of it as a shortcut to your project that you can open in the current window or a new window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vetur (Pine Wu)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X68GDC9V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l797wjk6z984ru7exnkl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X68GDC9V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l797wjk6z984ru7exnkl.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use Vue, you already know about this. If you don't, then you probably don't need it or want it.&lt;/p&gt;

&lt;h2&gt;
  
  
  VsCode Action Buttons (Seun LanLege)
&lt;/h2&gt;

&lt;p&gt;Some people might think this is unnecessary, but I absolutely love this extension! I don't love using the command line, but I end up using it a lot for things like &lt;code&gt;npm run dev&lt;/code&gt; or &lt;code&gt;bash deploy.sh&lt;/code&gt;. You can skip the typing, and set up an action button for a command (which will run that command in the command line).&lt;/p&gt;

&lt;h2&gt;
  
  
  vscode-pdf (tomoki1207)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oguwgS-9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlyni7d2enie3cyzyu6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oguwgS-9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlyni7d2enie3cyzyu6g.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have a PDF in your window, by default VS Code won't show it. With this extension it will open up in the window just like a browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue Peek (Dario Fuzinato)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9ArrrcDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6pdphgxskj37wpoka8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ArrrcDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6pdphgxskj37wpoka8j.png" alt="image" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will let you command/control + click a component and it will open up that component. Or you can just look at it inline. &lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>vscode</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Host Website on GitHub Pages (The Easy Way)</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Sat, 07 Aug 2021 05:44:45 +0000</pubDate>
      <link>https://dev.to/ngblaylock/host-website-on-github-pages-the-easy-way-4mfl</link>
      <guid>https://dev.to/ngblaylock/host-website-on-github-pages-the-easy-way-4mfl</guid>
      <description>&lt;p&gt;Ever since my first class on web development, I have loved making websites. I loved the classes, I loved learning about HTML, CSS, and JavaScript. I loved everything about it, except when it came time for publishing a website. Sure, it was nice that you can make a site, but what good is it if you can't access it on any computer. Those classes went in to this big thing on how to get a free trial from some company, that has these complex server setups, and a FTP setup that you need to configure, and then after all these steps, which you are never going to remember, you have a website. So the purpose of this post is to publish a basic static website for beginners for free with minimal setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;If you aren't familiar with GitHub, you should look into it. I am not going to go in depth with it here, but just know that if you are writing code, it would be worth your while to set up some version control with Git. GitHub is like your cloud storage for your code, except that you can also choose to host a static website from it as well. So if you haven't set up your GitHub account, do that first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a repository
&lt;/h2&gt;

&lt;p&gt;When you are in GitHub, create a new repository. For those of you who are new to this, a repository is basically just a new project. If your end goal is to host one site, you probably want to host your website at the root of your account. The URL for your site will be &lt;code&gt;&amp;lt;username&amp;gt;.github.io&lt;/code&gt;. When setting up your repository, your repository name should be &lt;code&gt;&amp;lt;username&amp;gt;.github.io&lt;/code&gt; so GitHub knows that you want to host this file at the root. I would recommend this for the first site you create. You can always change this later. If you name your repository anything else, like &lt;code&gt;easy-hosting&lt;/code&gt; your site will be hosted at &lt;code&gt;&amp;lt;username&amp;gt;.github.io/easy-hosting&lt;/code&gt;. This second example could have some issues if you ever use absolute links (ex. &lt;code&gt;&amp;lt;a href="/about"&amp;gt;About&amp;lt;/a&amp;gt;&lt;/code&gt;). That will be looking for the page &lt;code&gt;&amp;lt;username&amp;gt;.github.io/about&lt;/code&gt; rather than &lt;code&gt;&amp;lt;username&amp;gt;.github.io/easy-hosting/about&lt;/code&gt;. We will get to a fix for this in a second.&lt;/p&gt;

&lt;p&gt;Whichever direction you go, make sure that you use a public repository. You cannot host a website on GitHub in the free tier using a private repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3rc1tWo8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1s3w9mus76y2k7y2pfy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3rc1tWo8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1s3w9mus76y2k7y2pfy7.png" alt="Create new Repo Screenshot" width="730" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding code to GitHub
&lt;/h2&gt;

&lt;p&gt;There are three pretty easy ways to add code to GitHub. The first way is not what I recommend, but you can still do it. You can upload your code from your computer and just stick it in the repository. This gets clunky very fast, and is a pain to work with. Don't do this. &lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Desktop
&lt;/h3&gt;

&lt;p&gt;The second way is to use &lt;a href="https://desktop.github.com/"&gt;GitHub Desktop&lt;/a&gt; which is a desktop application that handles all of your git commands for you, and can link your local files on your computer to your GitHub account online. When I first started with Git, I didn't know a single thing about the command line like traditional Git courses teach you. I got along just fine for a few years because of GitHub Desktop.&lt;/p&gt;

&lt;p&gt;If you go this route, and have GitHub Desktop setup, you can choose from GitHub's website to set this repository up on your local machine from GitHub Desktop. From there it is pretty much straight forward. The app will set up your repository on your local machine and you can put your code there. Then it is just a matter of pushing your code up to your GitHub repository online.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code
&lt;/h3&gt;

&lt;p&gt;The third way, and my preferred way is to use Visual Studio Code. I write all my code in VS Code and love it. VS Code has a built-in Git user interface, so like GitHub Desktop, you don't need to use the command line for simple things. In the bottom left corner of the window, you can log in to your GitHub account. Sign in there. The default editor will also have more icons on the top right, and you can manage your git integration on the third one down titled "Source Control". This is very similar to GitHub Desktop, except that you don't need to leave your editor to do anything.&lt;/p&gt;

&lt;p&gt;From here you may just need to clone your repository using the command line. Follow the instructions in the GitHub repository that you set up.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Little Background
&lt;/h2&gt;

&lt;p&gt;Those steps were a little vague, so you may need some additional help from other blogs or videos to get your code online. The point was to get your HTML files and other assets in your online repository from your local machine. Now here is where I feel like this post is different than most other tutorials. A few years ago the only way to host a site on GitHub was to have a branch called &lt;code&gt;gh-pages&lt;/code&gt; and if you set it up, it would use files on that branch for hosting. Then they let you use your master branch as well, but only what was in the &lt;code&gt;/docs&lt;/code&gt; directory. That isn't the case anymore. You can now use any branch, and you can use the root of that branch or the docs directory. Unfortunately, at the time of this writing, you can't choose a specific folder for hosting. &lt;/p&gt;

&lt;h2&gt;
  
  
  Set up Hosting
&lt;/h2&gt;

&lt;p&gt;At this point, you should have a repository, a branch (probably &lt;code&gt;main&lt;/code&gt;), and at the very minimum an &lt;code&gt;index.html&lt;/code&gt; file in the root of the repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rN1cmovT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xeas02py5khgs7a0oq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rN1cmovT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xeas02py5khgs7a0oq4.png" alt="dashboard screenshot" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your repository's settings. &lt;/li&gt;
&lt;li&gt;In the left navigation, near the bottom, click on "Pages".&lt;/li&gt;
&lt;li&gt;Under the "Source", change it from &lt;code&gt;none&lt;/code&gt; to your branch (probably &lt;code&gt;main&lt;/code&gt;). Leave the folder at &lt;code&gt;root&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Save the setting. You should see a new popup that says &lt;code&gt;Your site is ready to be published at https://&amp;lt;username&amp;gt;.github.io/easy-hosting/&lt;/code&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---PrkFtAE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gc5li4b1uokybhvs5ynq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---PrkFtAE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gc5li4b1uokybhvs5ynq.png" alt="Settings Screenshot" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your site is now live! Any time that you commit and push your code to GitHub on the same branch, your website will automatically update. It's pretty slick.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The following sections are extra information that you may or may not need, but would be good to know about.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Domain
&lt;/h2&gt;

&lt;p&gt;This setup I just explained got me by for a while, but remember how I mentioned absolute links? Wouldn't it be nice to setup your own custom domain and subdomains rather than subfolders? Well, you can, and it is very easy. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you use a custom domain, be prepared to pay for it every year. It is about $12 on the low end. It isn't much, but just be aware of this.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I choose to purchase my domains from &lt;a href="https://domains.google.com"&gt;Google Domains&lt;/a&gt;. Go find a domain and purchase it. Once you have it purchased, go into its configuration and find "DNS" in the left navigation. Enter the following configuration so that it matches:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Host Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;TTL&lt;/th&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;domain&amp;gt;.com&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;185.199.108.153&lt;br&gt;185.199.109.153&lt;br&gt;185.199.110.153&lt;br&gt;185.199.111.153&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;www.&amp;lt;domain&amp;gt;.com&lt;/td&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;&amp;lt;username&amp;gt;.github.io&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;sub&amp;gt;.&amp;lt;domain&amp;gt;.com&lt;/td&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;&amp;lt;username&amp;gt;.github.io&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short, the first line is your domain mapped to GitHub's servers. The second uses the &lt;code&gt;www&lt;/code&gt; subdomain, which is pretty common. The third is to have your own subdomain. This is especially helpful for repositories like our &lt;code&gt;easy-hosting&lt;/code&gt; repository. If we host our site on &lt;code&gt;easy-hosting.&amp;lt;domain&amp;gt;.com&lt;/code&gt;, we can use absolute links, which will point absolute links to where we would expect it. &lt;/p&gt;

&lt;p&gt;There is one more step to get this to work. We need to go back to GitHub and in our Pages setting. Below the branch you entered earlier, there is a section for a Custom Domain. Enter your custom domain (&lt;code&gt;&amp;lt;sub&amp;gt;.&amp;lt;domain&amp;gt;.com&lt;/code&gt; or &lt;code&gt;&amp;lt;domain&amp;gt;.com&lt;/code&gt;) and save it. If you go back to your repository home page and look at your code, you will see that it created a &lt;code&gt;CNAME&lt;/code&gt; file in it with your custom domain in it. That is really all the setup that you need. It might take 20 minutes to a few hours for GitHub to configure some things in the backend. So go take a walk or something. &lt;/p&gt;

&lt;h2&gt;
  
  
  Static Site Generators and Single Page Applications
&lt;/h2&gt;

&lt;p&gt;Maybe you really don't want to spend a penny on this, but want to use absolute links in your project. Well, there is another workaround for this, but it takes a little more experience, and I won't really cover it much here. If you are building a serious website, you are hopefully at least using a static site generator like &lt;a href="https://11ty.dev"&gt;11ty&lt;/a&gt;, &lt;a href="https://nuxtjs.org"&gt;Nuxt&lt;/a&gt;, or just a single page application tool like &lt;a href="https://vuejs.org"&gt;Vue&lt;/a&gt;. Each of these have ways to set the root of your project using a path prefix. Here is &lt;a href="https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix"&gt;11ty's configuration&lt;/a&gt;, &lt;a href="https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-router#base"&gt;Nuxt's configuration&lt;/a&gt;, and &lt;a href="https://cli.vuejs.org/config/#publicpath"&gt;Vue's configuration&lt;/a&gt;. I am sure if you are using something else, it will have a similar configuration for you.&lt;/p&gt;

&lt;p&gt;Changing those configurations will allow you to use absolute links, and still host your site on &lt;code&gt;&amp;lt;username&amp;gt;.github.io/&amp;lt;repository&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While we are talking about this, because GitHub will only allow you to host from the root or docs directory, you would also want to configure your tool to output your files to the docs directory. For example, 11ty will generate the files to the &lt;code&gt;_site&lt;/code&gt; directory, and Nuxt will output the files to the &lt;code&gt;dist&lt;/code&gt; directory. You can get around that with &lt;a href="https://www.11ty.dev/docs/config/#output-directory"&gt;11ty's configuration&lt;/a&gt;, &lt;a href="https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-generate#dir"&gt;Nuxt's configuration&lt;/a&gt;, and &lt;a href="https://cli.vuejs.org/config/#outputdir"&gt;Vue's configuration&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Hopefully some parts of this have helped some of you out there. I can't say that GitHub pages is the best place to host a website, but for beginner projects, it is the perfect place to start. It is free, easy, and configurable. If you have any questions, just let me know if the comments.&lt;/p&gt;

</description>
      <category>github</category>
      <category>jamstack</category>
      <category>hosting</category>
    </item>
    <item>
      <title>Encrypt Static Nuxt Site</title>
      <dc:creator>Nathan Blaylock</dc:creator>
      <pubDate>Fri, 30 Jul 2021 18:37:06 +0000</pubDate>
      <link>https://dev.to/ngblaylock/encrypt-static-nuxt-site-2p0o</link>
      <guid>https://dev.to/ngblaylock/encrypt-static-nuxt-site-2p0o</guid>
      <description>&lt;p&gt;As a JAMStack developer, I often run into limitations in some of the projects that I am working on. I find that most of these limitations can be solved by using third-party tools, and actually work pretty well. However, these usually come with a price tag, which is totally fair and cool, but when I am not making money on a project, that seems overkill. This specific project I was working on needed to be password protected. That is pretty fair. A lot of projects need to have some content behind lock and key, but JAMStack sites may not be the best or easiest way to go about this. I set out to find a way that would make it possible to fully protect content on a page. &lt;/p&gt;

&lt;p&gt;The first thing that I looked into was using vanilla JavaScript. A lot of you are thinking right now that it wouldn't be the best option, and you would be right. I have used front-end "Authentication" by having the user put in a password and it would toggle the visibility of the information. That works in some cases where you want the content protected from the public. To be fair, only 99% of people visiting the site would even know how to dig into the JavaScript code and figure out what is going on, and even less would care to spend a few hours figuring it out. For this specific project, I wanted a little more protection than that offered. &lt;/p&gt;

&lt;p&gt;My next stop was looking at &lt;a href="https://firebase.google.com/docs/auth"&gt;Firebase Authentication&lt;/a&gt;. This is pretty sweet, and is designed for JAMStack sites like what I was building. However, the more I thought about it, the authentication wouldn't protect my static content. Firebase Authentication will only protect the content stored in Firebase, such as Firestore or RealtimeDB. So my static HTML code could still be accessed by someone who really wanted to get the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staticrypt
&lt;/h2&gt;

&lt;p&gt;I kept searching and stumbled accross &lt;a href="https://robinmoisson.github.io/staticrypt/"&gt;Staticrypt&lt;/a&gt;. This looked pretty promising. This is based on the &lt;a href="https://github.com/brix/crypto-js"&gt;crypto.js library&lt;/a&gt; and will take a full HTML page and encrypt it. The user will then need to enter the password for the script to un-encrypt it. It sounded pretty neat. I plugged in some HTML code and a password to the site to test it out, and sure enough, it spat out an encrypted page. It looked promising enough to look further into.&lt;/p&gt;

&lt;h2&gt;
  
  
  Website Build Tools
&lt;/h2&gt;

&lt;p&gt;The next step was to look at what type of website building tools I wanted to use. I was testing Staticrypt with the CLI and thought for sure that I was going to need to use a single page application, because it would only encrypt one file. But then I found this little snippet and that changed a lot:&lt;br&gt;
&lt;/p&gt;

&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;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.html"&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; staticrypt &lt;span class="o"&gt;{}&lt;/span&gt; mypassword &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That script when ran in the terminal will find each HTML file in your directory and encrypt it. With that, my first thought was to use &lt;a href="https://www.11ty.dev/"&gt;Eleventy&lt;/a&gt;. I really am a big fan of Eleventy. I had a grandiose idea one day to make something that wasn't nearly as cool or easy to use as Eleventy. I started playing with some scripts and a test Eleventy page, and found an issue after a few hours of work. When you encrypt each HTML page, you need to pass in a password for each page you navigate to. So I tried a few workarounds like storing the password in the users localstorage, and on each page, populating the input and submitting the form. It was a little glitchy, and it certainly didn't have a good user experience with the quick flashes of a password page. So I tried something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nuxt to the rescue!
&lt;/h2&gt;

&lt;p&gt;I am a really big fan of &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt;, but I really like developing with it using &lt;a href="https://nuxtjs.org/"&gt;Nuxt&lt;/a&gt;. I especially like the auto-routing based on your directory structure, the auto-importing components, and a lot of other awesome &lt;a href="https://modules.nuxtjs.org/"&gt;modules&lt;/a&gt; that are easy to incorporate. This would have been a lot easier project to set up if I just created a Vue project, but I like developing with Nuxt so much that I went through some extra hassle with the setup that I want to share with others. Keep in mind, this is not the cleanest or best solution, and there is room for improvements. So if you find a better way of implementing it, let me know in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting a Nuxt Site
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This assumes that you have some prior knowledge with Nuxt.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a standard Nuxt site: &lt;code&gt;npx create-nuxt-app nuxt-encrypt&lt;/code&gt; (When asked for the deployment target, use &lt;code&gt;static&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Create multiple Nuxt pages (ex. about.vue, cool.vue) and add some simple navigation.&lt;/li&gt;
&lt;li&gt;Test out the site with &lt;code&gt;npm run dev&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So that is the quickest Nuxt site I know how to setup for this. Running the project in development mode will hot reload the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Staticrypt
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Warning: I have only tested this on a Mac and Linux using the standard terminals.&lt;/strong&gt; If you are on Windows, you may need some modifications. Let me know in the comments if there are better cross-operating system alternatives.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Staticrypt: &lt;code&gt;npm i staticrypt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a new file to the root of the project called &lt;code&gt;remove-unencrypted.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adjust the &lt;code&gt;package.json&lt;/code&gt; scripts section.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;package.json&lt;/code&gt; Snippet&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nuxt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nuxt start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"generate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nuxt generate &amp;amp;&amp;amp; npm run encrypt &amp;amp;&amp;amp; npm run remove_unencrypted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"encrypt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd dist &amp;amp;&amp;amp; find . -type f -name '*.html' -exec npx staticrypt {} custompassword &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remove_unencrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node remove-unencrypted"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;remove-unancrypted.js&lt;/code&gt; File&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;fileList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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;fileList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;html$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&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="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;src&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="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;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;fileList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&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;src&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="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;fileList&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Replacing Encrypting Files...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;filesArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filesArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_encrypted&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Replaced &lt;/span&gt;&lt;span class="dl"&gt;"&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rename&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_encrypted&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="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating Static HTML Files
&lt;/h2&gt;

&lt;p&gt;This works pretty good straight out of the box. When we run &lt;code&gt;npm run generate&lt;/code&gt; it will do a little more than just generate static files. The first command, &lt;code&gt;nuxt generate&lt;/code&gt; does the standard generate command, and turns everything into a static HTML page and places them in the &lt;code&gt;dist&lt;/code&gt; directory. &lt;/p&gt;

&lt;p&gt;The second command, &lt;code&gt;npm run encrypt&lt;/code&gt; will encrypt each one of those HTML pages in the &lt;code&gt;dist&lt;/code&gt; directory. Note that in the &lt;code&gt;encrypt&lt;/code&gt; script, this example sets the password to &lt;code&gt;coolpassword&lt;/code&gt;. You can change this to be whatever you want. It should be a string with no spaces. &lt;/p&gt;

&lt;p&gt;The third script is to remove the unencrypted files. If you miss this step, what happens is it will encrypt the contents of one file, then save it as a copy. For example, index.html -&amp;gt; index_encrypted.html. This is what the &lt;code&gt;remove-unencrypted.js&lt;/code&gt; file does. It will recursively go through your project, find any HTML file with &lt;code&gt;_encrypted&lt;/code&gt; in it and rename it, which in turn replaces the original file. I don't have much experience writing Node files, so there might be a better script out there for this, but my script gets the job done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Previewing your Files
&lt;/h2&gt;

&lt;p&gt;Running &lt;code&gt;npm run generate&lt;/code&gt; should leave a few cues in the console on what is going on. Hopefully you don't get any errors. Once those three commands are finished, then you can run &lt;code&gt;npm run start&lt;/code&gt;. This starts the files in your &lt;code&gt;dist&lt;/code&gt; directory in it's own server. You should see when you go to your localhost page that you are now prompted with a password. Enter the password you set in the &lt;code&gt;encrypt&lt;/code&gt; script (in this case, &lt;code&gt;coolpassword&lt;/code&gt;), and you should have access to your content! Just for fun, look at the source code for the file loaded in. There will be no trace of your original code. It will just be the password page, and a bunch of gobbledegook. That gobbledegook is your content.&lt;/p&gt;

&lt;p&gt;Remember how I said that I tried this with 11ty first? My issue with 11ty was that on every page, we needed to put in a password? Well, with Nuxt, we don't need to worry about that. Nuxt does create an individual page for each file, but once you open the file, the SPA side of Nuxt takes over. That means that navigating to new pages doesn't do a new HTTP request, but loads in the content via JavaScript. &lt;/p&gt;

&lt;p&gt;There is a caveat to this. Be sure that when you use page navigation, you use &lt;code&gt;&amp;lt;nuxt-link&amp;gt;&lt;/code&gt; rather than an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag. If you use the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag, then you might as well just use something like 11ty, and figure out a workaround for the password prompt every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;There is always going to be some issues with everything. For example, since this page is loaded in via JavaScript, you will notice that the code for each page is technically in a JavaScript file, and that DOES NOT get encrypted (as well as images or other files). The JavaScript files are obscurely named, and I do not see them in the sources in a browser console, so I figure it is pretty safe. Staticrypt also mentions that it isn't flawless, so they don't recommend putting very sensitive things like banking on there. So take a deep look at what it is that you are protecting. Maybe you just need to pay a company for a better solution. For me, and my project, this works just fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Customizing the Password Page
&lt;/h2&gt;

&lt;p&gt;You can also modify the HTML password protected template page to your liking. Staticrypt's documentation shows this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  -f, --file-template  Path to custom HTML template with password prompt.
                          [string] [default: "[...]/cli/password_template.html"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you go into your &lt;code&gt;node-modules&lt;/code&gt; and find that &lt;code&gt;password_template.html&lt;/code&gt; file, you can copy that to the root of your project and modify it. Then change your &lt;code&gt;encrypt&lt;/code&gt; script to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"encrypt": "cd dist &amp;amp;&amp;amp; find . -type f -name '*.html' -exec npx staticrypt {} coolpassword -f=../password_template.html \\;",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;npm run encrypt&lt;/code&gt; will then use your password template from the root of your project instead.&lt;/p&gt;

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

&lt;p&gt;So, if you are looking for a simple way to password-protect your static website, consider using Staticrypt with Nuxt. It is easy to set up for basic usage, and produces a pretty secure website.&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>javascript</category>
      <category>nuxt</category>
    </item>
  </channel>
</rss>
