<?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: Craig Holliday</title>
    <description>The latest articles on DEV Community by Craig Holliday (@craigaholliday).</description>
    <link>https://dev.to/craigaholliday</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%2F142477%2F4f19b723-92c3-4fd4-9f1e-f7fb8d50baba.png</url>
      <title>DEV Community: Craig Holliday</title>
      <link>https://dev.to/craigaholliday</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/craigaholliday"/>
    <language>en</language>
    <item>
      <title>Adding a CSS playground to your Astro site with Svelte</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Sun, 19 Nov 2023 01:50:06 +0000</pubDate>
      <link>https://dev.to/craigaholliday/adding-a-css-playground-to-your-astro-site-with-svelte-11g</link>
      <guid>https://dev.to/craigaholliday/adding-a-css-playground-to-your-astro-site-with-svelte-11g</guid>
      <description>&lt;p&gt;I've recently updated my website using Astro. To continue experimenting with Astro, I added Svelte components to the site.&lt;/p&gt;

&lt;p&gt;If you didn't know, Astro has &lt;a href="https://docs.astro.build/en/core-concepts/framework-components/"&gt;integrations for React, Preact, Svelte, Vue, SolidJS, AlpineJS, and Lit&lt;/a&gt; (which is insane)&lt;/p&gt;

&lt;p&gt;This means I can bring what I've been learning with Svelte straight into my new personal website without much hassle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I want to do
&lt;/h2&gt;

&lt;p&gt;With this quick experiment, I want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the Svelte integration to my website&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://github.com/microsoft/monaco-editor"&gt;Monaco Editor&lt;/a&gt; to add code editors&lt;/li&gt;
&lt;li&gt;Create two editors: one editor for CSS and one for HTML&lt;/li&gt;
&lt;li&gt;Take the output from those editors and load them into an iFrame.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's do it
&lt;/h2&gt;

&lt;p&gt;I'll go step by step and show the code I used because this was super easy to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add the Svelte integration
&lt;/h3&gt;

&lt;p&gt;If I put any info here, I would repeat the fantastic Astro documentation.&lt;/p&gt;

&lt;p&gt;So, go to the &lt;a href="https://docs.astro.build/en/guides/integrations-guide/svelte/"&gt;fantastic documentation for this step&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was dead simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add code editors with Monaco Editor
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/monaco-editor"&gt;Monaco Editor&lt;/a&gt; was also relatively simple to add.&lt;/p&gt;

&lt;p&gt;Add the NPM package:&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 monaco-editor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, write a little wrapper around the package to create a Svelte component. This could be cleaner, but it gets the job done. I'm also using Tailwind CSS, by the way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// Editor.svelte
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;monaco&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monaco-editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;editorWorker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monaco-editor/esm/vs/editor/editor.worker?worker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cssWorker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monaco-editor/esm/vs/language/css/css.worker?worker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;htmlWorker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;monaco-editor/esm/vs/language/html/html.worker?worker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;html_code&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./html_code&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;css_code&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./css_code&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;editorElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLDivElement&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;editor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;monaco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IStandaloneCodeEditor&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;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;monaco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ITextModel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;onMount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MonacoEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;getWorker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;less&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cssWorker&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;handlebars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;razor&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;htmlWorker&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;editorWorker&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;monaco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editorElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;automaticLayout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vs-dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;minimap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onDidChangeModelContent&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;default_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;html_code&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;css_code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;monaco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;default_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;onDestroy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;monaco&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getModels&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;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-full w-full"&lt;/span&gt; &lt;span class="na"&gt;bind:this=&lt;/span&gt;&lt;span class="s"&gt;{editorElement}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This class manages the lifecycle of the editor and provides a Svelte component that can be used elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a CSS and HTML editor
&lt;/h3&gt;

&lt;p&gt;We need to use the Editor component we just made in another component.&lt;/p&gt;

&lt;p&gt;We make another component to wrap all of our logic rather than putting the logic in the page itself because we have to use a &lt;a href="https://docs.astro.build/en/reference/directives-reference/#client-directives"&gt;client directive&lt;/a&gt;, which we'll cover in a minute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// CSSPlayground.svelte
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Editor&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/css_playground/Editor.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Variables to bind the editors to&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;css_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;html_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- 2. Setup and bind the Editor components --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-64 w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Editor&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"html"&lt;/span&gt; &lt;span class="na"&gt;bind:content=&lt;/span&gt;&lt;span class="s"&gt;{html_code}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-64 w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Editor&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"css"&lt;/span&gt; &lt;span class="na"&gt;bind:content=&lt;/span&gt;&lt;span class="s"&gt;{css_code}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All this code has is a layout for the editors and the reference to the strings for the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load the CSS and HTML into an iFrame
&lt;/h3&gt;

&lt;p&gt;We have a small addition to the previous component and have the iFrame set up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// CSSPlayground.svelte
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Editor&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/components/css_playground/Editor.svelte&lt;/span&gt;&lt;span class="dl"&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;css_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&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;html_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Load the HTML and CSS code into the iFrame whenever it changes&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;load_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;css_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iFrame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iFrame&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLIFrameElement&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;iFrame&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;iFrame&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iframe_document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;iFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentWindow&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;iframe_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;iframe_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html_code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;css_code&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;iframe_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;iFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&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;iframe_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollWidth&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;iFrame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&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;iframe_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&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="c1"&gt;// 2. React whenever html_code or css_code changes&lt;/span&gt;
  &lt;span class="nl"&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;load_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;css_code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-64 w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Editor&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"html"&lt;/span&gt; &lt;span class="na"&gt;bind:content=&lt;/span&gt;&lt;span class="s"&gt;{html_code}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-64 w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Editor&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"css"&lt;/span&gt; &lt;span class="na"&gt;bind:content=&lt;/span&gt;&lt;span class="s"&gt;{css_code}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
// 3. Add the iFrame
&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"renderer"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"iFrame"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This is the most basic way I saw to load the HTML and CSS code into an iFrame. This could be improved.&lt;/p&gt;

&lt;p&gt;One problem is that the iFrame needs to be more responsive.&lt;/p&gt;

&lt;p&gt;Let me know if you know how to make the iFrame responsive to the browser and the inside elements at all times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add the Svelte component to the Astro page
&lt;/h3&gt;

&lt;p&gt;Finally, as shown below, we add our &lt;code&gt;CSSPlayground&lt;/code&gt; component to any Astro pages with the client directive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// css_playground.astro
---
import PageLayout from '@/layouts/Base';
import CSSPlayground from '../components/css_playground/CSSPlayground.svelte';

const meta = {
  title: 'CSS Playground',
  description: 'A cool css experiment',
};
---

&lt;span class="nt"&gt;&amp;lt;PageLayout&lt;/span&gt; &lt;span class="na"&gt;meta=&lt;/span&gt;&lt;span class="s"&gt;{meta}&lt;/span&gt; &lt;span class="na"&gt;body_class=&lt;/span&gt;&lt;span class="s"&gt;'w-full m-0 px-4 pt-2 max-w-none'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'space-y-6 flex flex-col'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'title mb-4'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Cool CSS&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--  1. This client directive tells Astro to load this on the client, not the server. --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;CSSPlayground&lt;/span&gt; &lt;span class="na"&gt;client:only=&lt;/span&gt;&lt;span class="s"&gt;'svelte'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/PageLayout&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  All done!
&lt;/h2&gt;

&lt;p&gt;That's all!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://www.craigaholliday.com/css_playground"&gt;You can find the deployed playground here.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's not a huge feature, but seeing how easy it is to add Svelte (or any other framework integration) to an Astro site is fascinating.&lt;/p&gt;

&lt;p&gt;I'm already a fan of Astro, and these simple integrations only solidify that fandom.&lt;/p&gt;

&lt;p&gt;Let me know your favorite thing about Astro!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>astro</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Use Astro for your personal or portfolio website</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Sun, 12 Nov 2023 04:02:50 +0000</pubDate>
      <link>https://dev.to/craigaholliday/use-astro-for-your-personal-or-portfolio-website-4lp0</link>
      <guid>https://dev.to/craigaholliday/use-astro-for-your-personal-or-portfolio-website-4lp0</guid>
      <description>&lt;h2&gt;
  
  
  TL:DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Astro is a fantastic framework.&lt;/li&gt;
&lt;li&gt;It is super easy to get up and running.&lt;/li&gt;
&lt;li&gt;It has fantastic templates.&lt;/li&gt;
&lt;li&gt;Vercel makes it simple to deploy.&lt;/li&gt;
&lt;li&gt;You should use it for your next portfolio, blog, etc.&lt;/li&gt;
&lt;li&gt;Look at my website here: &lt;a href="https://www.craigaholliday.com/"&gt;https://www.craigaholliday.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I needed
&lt;/h2&gt;

&lt;p&gt;Long story short: I was laid off and needed a new personal website.&lt;/p&gt;

&lt;p&gt;Most of my work is under NDA and also not publicly available.&lt;/p&gt;

&lt;p&gt;For my website, I needed something more like a blog than a traditional portfolio website.&lt;/p&gt;

&lt;p&gt;However, like other portfolio websites, the site still needed to look decent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did
&lt;/h2&gt;

&lt;p&gt;I picked Astro because I've heard great things about it, and it was something new to try.&lt;/p&gt;

&lt;p&gt;I already &lt;a href="https://koalatea.io/"&gt;built a blog website with Gatsby&lt;/a&gt;, and it worked great. However, it is always good to try new things.&lt;/p&gt;

&lt;p&gt;So, I went to the &lt;a href="https://astro.build/"&gt;Astro website&lt;/a&gt; to read through some of the docs and showcases.&lt;/p&gt;

&lt;p&gt;Astro has a great set of &lt;a href="https://astro.build/themes/"&gt;starter themes&lt;/a&gt; you can pick from.&lt;/p&gt;

&lt;p&gt;Among the themes was an &lt;a href="https://astro.build/themes/details/astro-cactus/"&gt;excellent minimal theme&lt;/a&gt;, which you can copy as a template to a new GitHub repo. The readme for the repo covers how.&lt;/p&gt;

&lt;p&gt;After copying the repo template, I:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change a few variables in the site configurations.&lt;/li&gt;
&lt;li&gt;Made some minor changes to the CSS and a few small design tweaks&lt;/li&gt;
&lt;li&gt;Added the information for all the projects I have worked on for the last four years&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, the website was done, and I could deploy it.&lt;/p&gt;

&lt;p&gt;The obvious choice to do this was with Vercel, which was as easy as signing up for an account and pointing Vercel to my repo.&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Honestly, what took me the longest was writing the details for all of my projects. The rest was quick and easy.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is in my portfolio
&lt;/h2&gt;

&lt;p&gt;Instead of traditional portfolios with links to apps, screenshots, etc, my portfolio has the ~14 projects I have worked on for the past four years.&lt;/p&gt;

&lt;p&gt;My work is not publicly available, so this is my solution: a lot of text about the problems I solved and how.&lt;/p&gt;

&lt;p&gt;It feels very different from what others show, which can be good or bad.&lt;/p&gt;

&lt;p&gt;This is what I have because of my contracting work and working on a B2B product that was private.&lt;/p&gt;

&lt;p&gt;Let me know how you like it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hire me
&lt;/h2&gt;

&lt;p&gt;Finally, I did not make this post to only share an easy way to make a portfolio.&lt;/p&gt;

&lt;p&gt;I also made this post to shill for myself.&lt;/p&gt;

&lt;p&gt;I am actively looking for my next job and would love some help. The job search scene is brutal right now.&lt;/p&gt;

&lt;p&gt;I am a senior-level generalist software engineer with management experience. All of my projects go into detail on what I've done previously.&lt;/p&gt;

&lt;p&gt;I love working with great people on great products and am independent of specific platforms, frameworks, or technology.&lt;/p&gt;

&lt;p&gt;I appreciate sharing this post, my portfolio, LinkedIn, and website with anyone who needs my skillset!&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://www.craigaholliday.com/"&gt;https://www.craigaholliday.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/craigaholliday/"&gt;https://www.linkedin.com/in/craigaholliday/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Email: &lt;a href="mailto:hello@craigaholliday.com"&gt;hello@craigaholliday.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>astro</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Using the useReducer Hook in React with TypeScript </title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Wed, 19 May 2021 00:03:24 +0000</pubDate>
      <link>https://dev.to/craigaholliday/using-the-usereducer-hook-in-react-with-typescript-27m1</link>
      <guid>https://dev.to/craigaholliday/using-the-usereducer-hook-in-react-with-typescript-27m1</guid>
      <description>&lt;p&gt;The &lt;a href="https://reactjs.org/docs/hooks-reference.html#usereducer"&gt;useReducer&lt;/a&gt; hook is an alternative to the &lt;a href="https://reactjs.org/docs/hooks-reference.html#usestate"&gt;useState&lt;/a&gt; hook and is preferable when you have complex state logic or when your next state depends on your previous state.&lt;/p&gt;

&lt;p&gt;The useReducer hook accepts a reducer type &lt;code&gt;(state, action) =&amp;gt; newState&lt;/code&gt; and returns a state object paired with a dispatch method much like Redux.&lt;/p&gt;

&lt;p&gt;Now the official &lt;a href="https://reactjs.org/docs/hooks-reference.html#usereducer"&gt;useReducer documentation&lt;/a&gt; will show you how to define a reducer that accepts actions you will call with a dispatch method.&lt;/p&gt;

&lt;p&gt;That is a good use case but I have another example of using &lt;code&gt;useReducer&lt;/code&gt; to provide partial updates to state which I find covers the rest of my use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  useReducer with actions and a dispatch method
&lt;/h2&gt;

&lt;p&gt;The default example for &lt;code&gt;useReducer&lt;/code&gt; is set up for you to create a reducer function and provide it with an action. The action provided should have a type and some value to update the state.&lt;/p&gt;

&lt;p&gt;To strongly type this feature with TypeScript we can create an enum with all of our possible action types as well as create an interface for the action.&lt;/p&gt;

&lt;p&gt;Below is a fairly contrived example but shows the most basic example possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// An enum with all the types of actions to use in our reducer&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;CountActionKind&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;INCREASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INCREASE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;DECREASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DECREASE&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="c1"&gt;// An interface for our actions&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CountAction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CountActionKind&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// An interface for our state&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CountState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Our reducer function that uses a switch statement to handle our actions&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;counterReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CountState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CountAction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;CountActionKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INCREASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;CountActionKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DECREASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;default&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;state&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="c1"&gt;// An example of using the `useReducer` hooks with our reducer function and an initial state&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FunctionComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Calling our actions on button click */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CountActionKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INCREASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        -
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CountActionKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DECREASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  useReducer using the Partial type for state updates
&lt;/h2&gt;

&lt;p&gt;The next way of using &lt;code&gt;useReducer&lt;/code&gt; is best used when you have a state object where you need to change some values inside of it directly rather than dispatching an action to handle state changes.&lt;/p&gt;

&lt;p&gt;This way also has fewer types but does expose the state to be changed directly so take that into account when using this method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interface for our state&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LoadingState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The example component that use the `useReducer` hook with our state&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LoadingComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FunctionComponent&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="cm"&gt;/** 
   See here that we are using `newState: Partial&amp;lt;LoadingState&amp;gt;` in our reducer
   so we can provide only the properties that are updated on our state
   */&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoadingState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LoadingState&lt;/span&gt;&lt;span class="o"&gt;&amp;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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;newState&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="na"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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;// And here we provide only properties that are updating on the state&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;These are my two methods so check out the other posts below for other methods. It's beneficial to read the wide range of ways to accomplish the same thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.newline.co/@bespoyasov/how-to-use-usereducer-with-typescript--3918a332"&gt;https://www.newline.co/@bespoyasov/how-to-use-usereducer-with-typescript--3918a332&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.sumologic.com/blog/react-hook-typescript/"&gt;https://www.sumologic.com/blog/react-hook-typescript/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.benmvp.com/blog/type-checking-react-usereducer-typescript/"&gt;https://www.benmvp.com/blog/type-checking-react-usereducer-typescript/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟🌟🌟&lt;/p&gt;

&lt;p&gt;My brother and I write all the time about React, TypeScript, R, Data Science, you name it on our blog so check it out:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://koalatea.io"&gt;KoalaTea.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟🌟🌟&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Getting started with the Notion API JavaScript SDK</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Tue, 18 May 2021 17:30:57 +0000</pubDate>
      <link>https://dev.to/craigaholliday/getting-started-with-the-notion-api-javascript-sdk-c50</link>
      <guid>https://dev.to/craigaholliday/getting-started-with-the-notion-api-javascript-sdk-c50</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.notion.so/Getting-started-with-the-Notion-API-JavaScript-SDK-237536a12289464fa7ebfc3c70284343"&gt;public beta for the Notion API&lt;/a&gt; went live recently and it is going to make Notion 10x more powerful.&lt;/p&gt;

&lt;p&gt;That means it is the perfect time to jump on the bandwagon and start building integrations of your own.&lt;/p&gt;

&lt;p&gt;In this post let's go over how to get started with the Notion API by using the &lt;a href="https://github.com/makenotion/notion-sdk-js"&gt;Notion JavaScript SDK&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Account setup
&lt;/h2&gt;

&lt;p&gt;This is covered better with gifs in the &lt;a href="https://developers.notion.com/docs/getting-started"&gt;official getting started page&lt;/a&gt; so read through that for more detailed instructions.&lt;/p&gt;

&lt;p&gt;Here is a short outline of setting up your account and first integration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a Notion account (If you don't already have one)&lt;/li&gt;
&lt;li&gt;Create a workspace or log into one as an Admin&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.notion.com/docs/getting-started#create-a-new-integration"&gt;Create a new integration&lt;/a&gt;. Save the &lt;code&gt;Internal Integration Token&lt;/code&gt; because we will be using that later.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.notion.com/docs/getting-started#share-a-database-with-your-integration"&gt;Share a database with your integration&lt;/a&gt;. You have to share databases with the integration for security purposes. You can have tons of databases on a single Notion account so it wouldn't be the best if an integration received access to everything connected to one account.&lt;/li&gt;
&lt;li&gt;Copy the &lt;code&gt;Database ID&lt;/code&gt;. When I set this up I had Notion up in my browser so the URL with the &lt;code&gt;Database ID&lt;/code&gt; looked like this &lt;code&gt;https://www.notion.so/${DATABASE_ID}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You are ready to go!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Ways to explore the Notion API
&lt;/h2&gt;

&lt;p&gt;Before going into our example I want to say there are so many cool ways to explore the Notion API.&lt;/p&gt;

&lt;p&gt;We will be using the &lt;a href="https://github.com/makenotion/notion-sdk-js"&gt;Notion JavaScript SDK&lt;/a&gt; but there is also a &lt;a href="https://www.postman.com/notionhq/workspace/notion-s-public-api-workspace/overview"&gt;Postman Workspace&lt;/a&gt; which I highly recommend taking a look at.&lt;/p&gt;

&lt;p&gt;There are also a couple of &lt;a href="https://developers.notion.com/page/examples"&gt;integration examples&lt;/a&gt; you can check out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Project
&lt;/h2&gt;

&lt;p&gt;Let's hop into some code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Setup
&lt;/h3&gt;

&lt;p&gt;Navigate to where you want to create your project.&lt;/p&gt;

&lt;p&gt;Create your example folder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir notion-api-example &amp;amp;&amp;amp; cd notion-api-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize your project with NPM. (Using &lt;code&gt;-y&lt;/code&gt; to say yes to all default configuration options)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the &lt;a href="https://github.com/makenotion/notion-sdk-js"&gt;Notion JavaScript SDK&lt;/a&gt;&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 @notionhq/client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an index file for our code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we will add a script to our &lt;code&gt;package.json&lt;/code&gt; to run our code.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;"start": "node index.js"&lt;/code&gt; and your &lt;code&gt;package.json&lt;/code&gt; should look like this:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"notion-api-example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&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;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&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;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&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;"node index.js"&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;"keywords"&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;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&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;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&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;"@notionhq/client"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.1.3"&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;h3&gt;
  
  
  Actual code
&lt;/h3&gt;

&lt;p&gt;Now open up &lt;code&gt;index.js&lt;/code&gt; and paste the code below. Then replace &lt;code&gt;INTERNAL_INTEGRATION_TOKEN&lt;/code&gt; with the token we saved in the setup and &lt;code&gt;DATABASE_ID&lt;/code&gt; with the Database ID we saved in the setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Require the Client object from the Notion JS SDK&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&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="s1"&gt;@notionhq/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create a notion client&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INTERNAL_INTEGRATION_TOKEN&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="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;databaseId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DATABASE_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Call `retrieve` on `databases` to retrieve a database object.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;databases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;database_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;databaseId&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="nx"&gt;response&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;With this code in place, we can now execute it by running the start script &lt;code&gt;npm run start&lt;/code&gt;. If the database id and your integration token are entered correctly you should see a log of the JSON representing the retrieved database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactor and creating a page
&lt;/h3&gt;

&lt;p&gt;Before we wrap up, let's refactor what we currently have and add a function to create a new page in our database.&lt;/p&gt;

&lt;p&gt;Change all the code in &lt;code&gt;index.js&lt;/code&gt; to the code below.&lt;/p&gt;

&lt;p&gt;This is a lot of code so check the added comments for what each piece of the code is doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&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="s1"&gt;@notionhq/client&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;notion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INTERNAL_INTEGRATION_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Refactor `retrieveDatabase` to a function&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;retrieveDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;databaseId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;databases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;database_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;databaseId&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Build a `createPageInDatabase` function&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createPageInDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;databaseId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// The parent object to add to. Here just the ID of the database but this can also be the id of a page.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;database_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;databaseId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Properties object. This has to match properties in the database.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Awesome New Page&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;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Children object that contains all the awesome Notion block objects.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heading_2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;heading_2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My awesome cool page&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;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="na"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paragraph&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I created my awesome new page while following along with the KoalaTea Getting started with the Notion API JavaScript SDK blog post. Now I should go read more KoalaTea blog posts. 😄&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://koalatea.io/&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;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="c1"&gt;// The page object where we put all our other objects together to create a new page.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Finally the request to create a page.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&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="nx"&gt;response&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;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})(&lt;/span&gt;&lt;span class="nx"&gt;createPageInDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DATABASE_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now executing this code (&lt;code&gt;npm run start&lt;/code&gt;) we should get a response telling us that a new page was created in our database.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do now?
&lt;/h2&gt;

&lt;p&gt;Now that you have gotten started with the Notion API you should look at the &lt;a href="https://developers.notion.com/reference"&gt;API documentation&lt;/a&gt; and &lt;a href="https://developers.notion.com/page/examples"&gt;code samples&lt;/a&gt; to see more fleshed-out details of what you can do with the API.&lt;/p&gt;

&lt;p&gt;After you have read through the rest of the documentation you should build a project. I suggest you try to build a CMS which is a fantastic project to explore the Notion API.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMS with the Notion API
&lt;/h3&gt;

&lt;p&gt;Here are some steps to build a Notion CMS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.fastify.io/"&gt;Build a simple Fastify server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Start with your database but take a look at &lt;a href="https://developers.notion.com/docs/authorization"&gt;user authentication&lt;/a&gt; so others could use the CMS.&lt;/li&gt;
&lt;li&gt;Build simple routes to retrieve data from a database based on certain property filters.&lt;/li&gt;
&lt;li&gt;Create routes to add pages to the database with just the title and description. (Adding blocks seems more complicated for the first project)&lt;/li&gt;
&lt;li&gt;Deploy to &lt;a href="https://www.heroku.com/"&gt;Heroku&lt;/a&gt; or &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If you have trouble, 🌟 &lt;a href="https://twitter.com/TheMrHolliday"&gt;ping me on Twitter&lt;/a&gt; 🌟&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/Getting-started-with-the-Notion-API-JavaScript-SDK-237536a12289464fa7ebfc3c70284343"&gt;Public beta for the Notion API&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.notion.com/docs/getting-started"&gt;Official getting started page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/makenotion/notion-sdk-js"&gt;Notion JavaScript SDK&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.postman.com/notionhq/workspace/notion-s-public-api-workspace/overview"&gt;Postman Workspace&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.notion.com/reference"&gt;API documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.fastify.io/"&gt;Build a simple Fastify server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.heroku.com/"&gt;Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟 &lt;a href="https://twitter.com/TheMrHolliday"&gt;ping me on Twitter&lt;/a&gt; 🌟&lt;/p&gt;

&lt;p&gt;🌟🌟🌟&lt;/p&gt;

&lt;p&gt;My brother and I write all the time about React, TypeScript, R, Data Science, you name it on our blog so check it out:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://koalatea.io"&gt;KoalaTea.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟🌟🌟&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to update all your NPM packages at once</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Tue, 04 May 2021 20:42:31 +0000</pubDate>
      <link>https://dev.to/craigaholliday/how-to-update-all-your-npm-packages-at-once-458j</link>
      <guid>https://dev.to/craigaholliday/how-to-update-all-your-npm-packages-at-once-458j</guid>
      <description>&lt;p&gt;You come back to a 6-month-old project that you haven't touched in a while and now all of your NPM packages are vastly out of date. That's just the speed at which web development moves.&lt;/p&gt;

&lt;p&gt;So you need to update all your packages, how can we do that?&lt;/p&gt;

&lt;h2&gt;
  
  
  The safe method
&lt;/h2&gt;

&lt;p&gt;NPM does provide a command to update packages. This is the command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm update --save/--save-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Though this only updates to the latest &lt;em&gt;minor version.&lt;/em&gt; For example, &lt;code&gt;1.0.5&lt;/code&gt; to &lt;code&gt;1.1.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So if we have a major version change like &lt;code&gt;1.0.5&lt;/code&gt; to &lt;code&gt;3.1.3&lt;/code&gt;, this command will only update to the highest version before &lt;code&gt;2.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A major version can introduce breaking changes to packages that can break your project. Because of this, the above command promotes manually updating packages.&lt;/p&gt;

&lt;p&gt;Manually updating your packages can be great to reduce the chance of a package breaking your application without you noticing.&lt;/p&gt;

&lt;p&gt;But we haven't touched this project in months and we want to get everything up to date that we know won't break our application (and if it does we will suffer the consequences).&lt;/p&gt;

&lt;h2&gt;
  
  
  The less-safe method
&lt;/h2&gt;

&lt;p&gt;To update our NPM packages we will reach for &lt;em&gt;another&lt;/em&gt; NPM package.&lt;/p&gt;

&lt;p&gt;This package is called &lt;code&gt;npm-check&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/npm-check" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/npm-check&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;npm-check&lt;/code&gt; will not just update your packages with no regard to the consequences. Instead, &lt;code&gt;npm-check&lt;/code&gt; will allow you to interactively check and choose what packages to update.&lt;/p&gt;

&lt;p&gt;To use &lt;code&gt;npm-check&lt;/code&gt; we will install it globally and then we can use the command to interactively update our packages.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;npm install -g npm-check&lt;/code&gt; to install the package globally.&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;npm-check&lt;/code&gt; command to interactively update packages&lt;/p&gt;

&lt;p&gt;When using the &lt;code&gt;npm-check&lt;/code&gt; command we will see the below in our command line allowing us to see what packages we can update.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnx122f3c3uwpruwo9pkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnx122f3c3uwpruwo9pkd.png" alt="Command line tool showing an interactive GUI for updating NPM packages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it!
&lt;/h2&gt;

&lt;p&gt;There are more ways to update your packages either automatically or with other packages, but this is a super simple one that you can start using today.&lt;/p&gt;

&lt;p&gt;Try this out the next time you have a project that needs to be updated!&lt;/p&gt;

&lt;h2&gt;
  
  
  Shameless Plug
&lt;/h2&gt;

&lt;p&gt;If you like what you read also check out my brother and my blog where we post this and tons of other content!&lt;br&gt;
👉 &lt;a href="https://koalatea.io/" rel="noopener noreferrer"&gt;https://koalatea.io/&lt;/a&gt; 👈&lt;/p&gt;

&lt;p&gt;&lt;a href="https://koalatea.io/how-to-update-all-your-npm-packages-at-once/" rel="noopener noreferrer"&gt;And here is this post on our blog!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>npm</category>
      <category>node</category>
    </item>
    <item>
      <title>How to start a TypeScript project [2021]</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Tue, 27 Apr 2021 23:39:44 +0000</pubDate>
      <link>https://dev.to/craigaholliday/how-to-start-a-typescript-project-2021-2h6l</link>
      <guid>https://dev.to/craigaholliday/how-to-start-a-typescript-project-2021-2h6l</guid>
      <description>&lt;p&gt;If you are learning TypeScript you can have a hard time finding out a simple way to start TypeScript projects from scratch. Depending on if you are coming from JavaScript or a statically typed language like Go, Swift, or Kotlin you may have an expectation for how your project should work.&lt;/p&gt;

&lt;p&gt;For my JavaScript friends, you may just want something to start working right now.&lt;/p&gt;

&lt;p&gt;For the statically typed crowd, you may want auto-completion, compiler errors in your IDE, and a simple zero-config compilation. For anything related to the IDE &lt;a href="https://code.visualstudio.com/docs/languages/typescript"&gt;use VSCode&lt;/a&gt; and you will be golden.&lt;/p&gt;

&lt;p&gt;To satisfy everyone, let's go over simple ways to set up a TypeScript project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep in mind
&lt;/h2&gt;

&lt;p&gt;TypeScript is a statically typed language that is a superset of JavaScript. Because of this TypeScript transcompiles to JavaScript.&lt;/p&gt;

&lt;p&gt;How? Well with a compiler of course. &lt;a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html"&gt;TypeScript compiler (TSC)&lt;/a&gt; or &lt;a href="https://babeljs.io/docs/en/babel-preset-typescript"&gt;Babel&lt;/a&gt; to be exact.&lt;/p&gt;

&lt;p&gt;No matter what platform or tool you are using, at some point, they will use a TypeScript compiler because at the end of the day we still have to execute JavaScript.&lt;/p&gt;

&lt;p&gt;If you want to learn the fundamentals of TypeScript go ahead and check out &lt;a href="https://www.typescriptlang.org/docs/handbook/"&gt;the official handbook&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a TypeScript Project (The absolute simplest way)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;In my opinion,&lt;/em&gt; the simplest way to execute JavaScript is by installing Node and running &lt;code&gt;node coolfile.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So &lt;em&gt;in my opinion,&lt;/em&gt; the easiest way to compile and execute TypeScript is by installed Node and a package called &lt;a href="https://github.com/TypeStrong/ts-node"&gt;ts-node&lt;/a&gt; and using &lt;a href="https://github.com/TypeStrong/ts-node"&gt;ts-node&lt;/a&gt; to execute your TypeScript the same way you would with node.&lt;/p&gt;

&lt;p&gt;The short of what &lt;a href="https://github.com/TypeStrong/ts-node"&gt;ts-node&lt;/a&gt; does is run node and tsc together to compile then run the compiled JavaScript in a single command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Locally in your project.
npm install -D typescript
npm install -D ts-node

# Or globally with TypeScript.
npm install -g typescript
npm install -g ts-node

# Execute a script as `node` + `tsc`.
ts-node script.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up a TypeScript Project (Libraries)
&lt;/h2&gt;

&lt;p&gt;There is another simple way to start a project for experimenting or for platform-agnostic libraries.&lt;/p&gt;

&lt;p&gt;The simple way is by using a &lt;a href="https://github.com/formium/tsdx"&gt;zero-config CLI called TSDX&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With this, you'll create a library with TSDX which will set up everything you need to run, build, lint, and test your project or library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tsdx create mylib
cd mylib
yarn start
yarn build
yarn lint
yarn test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I found out about TSDX via TailwindCSS's TailwindLabs GitHub where they have a &lt;a href="https://github.com/tailwindlabs/tailwindcss-intellisense"&gt;tailwindcss-intellisense&lt;/a&gt; project (a VSCode extension for Tailwind autocomplete, syntax highlighting, and linting). This project contains a &lt;a href="https://github.com/tailwindlabs/tailwindcss-intellisense/tree/master/packages/tailwindcss-language-service"&gt;"language service" package&lt;/a&gt; that is agnostic to the platform it is being used in hence TSDX being a good use case for the library.&lt;/p&gt;

&lt;p&gt;TSDX also works with React but I have not tried using it for that yet. I would usually rely on the CLI that comes with whatever framework I am using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a TypeScript Project (Frameworks)
&lt;/h2&gt;

&lt;p&gt;If you are starting a TypeScript project with a framework you are in luck, most if not all of the frameworks support TypeScript now.&lt;/p&gt;

&lt;p&gt;Let's go over a few frameworks to show the support and provide some useful links.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular
&lt;/h3&gt;

&lt;p&gt;Angular uses TypeScript as the primary language for development. So for Angular, all you have to do is continue to use the Angular CLI as usual.&lt;/p&gt;

&lt;p&gt;If you've been using Angular you are probably way ahead of the game on using TypeScript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.io/guide/typescript-configuration"&gt;https://angular.io/guide/typescript-configuration&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;For React we have some frameworks in our frameworks.&lt;/p&gt;

&lt;p&gt;Here are the most popular React frameworks and links about adding or their support for TypeScript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://create-react-app.dev/docs/adding-typescript/"&gt;Create React App&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.gatsbyjs.com/docs/how-to/custom-configuration/typescript/"&gt;Gatsby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/basic-features/typescript"&gt;Next.js&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue
&lt;/h3&gt;

&lt;p&gt;Vue 3 is written in TypeScript so there is no additional tooling needed to use TypeScript with Vue 3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://v3.vuejs.org/guide/typescript-support.html#official-declaration-in-npm-packages"&gt;https://v3.vuejs.org/guide/typescript-support.html#official-declaration-in-npm-packages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are still using Vue 2 for some reason, the Vue CLI still had support for TypeScript so you are all good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vuejs.org/v2/guide/typescript.html"&gt;https://vuejs.org/v2/guide/typescript.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Node
&lt;/h3&gt;

&lt;p&gt;Getting TypeScript set up with some Node.js frameworks has been a bit of a pain here and there but that is a larger discussion.&lt;/p&gt;

&lt;p&gt;The issue is really with getting these frameworks to be very strict with TypeScript.&lt;/p&gt;

&lt;p&gt;Either way, you should be able to set up TypeScript for &lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt; or &lt;a href="https://www.fastify.io/"&gt;Fastify&lt;/a&gt; fine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.logrocket.com/typescript-with-node-js-and-express/"&gt;Here's a quick Typescript with Express tutorial from LogRocket.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.fastify.io/docs/v1.14.x/TypeScript/"&gt;Fastify has Typescript support&lt;/a&gt; and I've recently used &lt;a href="https://www.npmjs.com/package/fastify-typescript-generator"&gt;this generator package&lt;/a&gt; to get a project started quickly. There were some small changes I made to the generated project to fit my TypeScript style.&lt;/p&gt;

&lt;p&gt;Lastly, take a look at &lt;a href="https://nestjs.com/"&gt;NestJS&lt;/a&gt; because this framework is doing a lot of cool stuff. It has full TypeScript support, is built like Angular, and unfortunately has a learning curve.&lt;/p&gt;

&lt;p&gt;I'm interested to hear about &lt;em&gt;your&lt;/em&gt; experience with Node frameworks and TypeScript so let me know!&lt;/p&gt;

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

&lt;p&gt;Those are some of the simple ways to start a project in TypeScript. TypeScript and web tooling can be scary and cumbersome as you are starting out. Especially if you are used to all-in-one platforms.&lt;/p&gt;

&lt;p&gt;TypeScript enables a great new way to develop web applications and can help a lot with some of the confusion for new developers jumping into web development. (Of course, that always comes with tradeoffs 😅)&lt;/p&gt;

&lt;p&gt;Remember to not get bogged down about a tool or tools to work correctly at first and don't try to do everything at once for your first TypeScript project.&lt;/p&gt;

&lt;p&gt;Most importantly, have fun!&lt;/p&gt;

&lt;p&gt;If you like what you read also check out my brother and my blog where we post this and tons of other content! &lt;br&gt;
👉 &lt;a href="https://koalatea.io/"&gt;https://koalatea.io/&lt;/a&gt; 👈&lt;/p&gt;

&lt;p&gt;&lt;a href="https://koalatea.io/how-to-start-a-typescript-project-2021/"&gt;And here is this post on our blog!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/"&gt;TypeScript Handbook&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/bootstrap"&gt;TypeScript Bootstrap (Lots of links to different tools and platforms)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/"&gt;VSCode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TypeStrong/ts-node"&gt;ts-node&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/formium/tsdx"&gt;TSDX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://create-react-app.dev/docs/adding-typescript/"&gt;Create React App&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.gatsbyjs.com/docs/how-to/custom-configuration/typescript/"&gt;Gatsby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/basic-features/typescript"&gt;Next.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.fastify.io/"&gt;Fastify&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nestjs.com/"&gt;NestJS&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;You are at the end of the post so legally you have to:&lt;br&gt;
🌟 &lt;a href="https://twitter.com/TheMrHolliday"&gt;Follow me on Twitter&lt;/a&gt; 🌟&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Ring Upp - DO Hackathon - Part 4/4 - Submission</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Wed, 06 Jan 2021 19:23:31 +0000</pubDate>
      <link>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-4-4-submission-4h10</link>
      <guid>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-4-4-submission-4h10</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I built a video chat app using WebRTC where you can chat with up to 3 people. This application works on mobile and desktop, allows you to screen-share, has other functionality you'd expect from a video app, and is the start of a bigger video chat application.&lt;/p&gt;

&lt;p&gt;Right now this application is minimal but has the beginnings of a commercial video app or more likely a module you can implement in other applications to provide video chat functionality. Other products like this would be &lt;a href="https://whereby.com/" rel="noopener noreferrer"&gt;Whereby&lt;/a&gt; and &lt;a href="https://www.daily.co/" rel="noopener noreferrer"&gt;Daily.co&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;p&gt;Built for Business&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ringupp.com/" rel="noopener noreferrer"&gt;https://ringupp.com/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkxk8ag5mh77kl37skzac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkxk8ag5mh77kl37skzac.png" alt="Screenshot of the Ring Upp landing page"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faicyc9i6rv50wna32aza.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faicyc9i6rv50wna32aza.png" alt="Screenshot of the Ring Upp page where you choose a name for a call"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdz9tqnvd9mh2ukvv7z53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdz9tqnvd9mh2ukvv7z53.png" alt="Screenshot of the Ring Upp video call where I am connected and showing my video twice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;Ring Upp is a video chat app where you can chat with up to 2 other people on mobile and desktop with no signup.&lt;/p&gt;

&lt;p&gt;The flow is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick a name for your chat&lt;/li&gt;
&lt;li&gt;Share the URL&lt;/li&gt;
&lt;li&gt;Start chatting&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The video chats are free, real-time, and HD quality utilizing WebRTC to connect clients directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/KoalaTeaCode/ringupp" rel="noopener noreferrer"&gt;https://github.com/KoalaTeaCode/ringupp&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://choosealicense.com/licenses/mit/" rel="noopener noreferrer"&gt;MIT&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I explained this a bit more in my series of posts but basically, this application has been on my to-do list for a long time. This hackathon was a great excuse to work on this side project. I have also been working on an app called &lt;a href="https://www.meetcafecito.com/" rel="noopener noreferrer"&gt;Cafecito&lt;/a&gt;, an app where you can meet new people remotely over video, with a fantastic team that I hope some of the takeaways from this project can help with.&lt;/p&gt;

&lt;p&gt;This is my first hackathon but since I've been in the &lt;a href="http://dev.to/"&gt;Dev.to&lt;/a&gt; community lately, I was inspired to give this one a try. I was not disappointed.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it
&lt;/h3&gt;

&lt;p&gt;More of this in my series of posts.&lt;/p&gt;

&lt;p&gt;That being said, I used App Platform to host my Node.js app which was simple and quick to set up. In this project, I also learned a lot about connecting peers using WebRTC which is a great bit of knowledge to have since WebRTC is continuing to gain traction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express JS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twilio.com/stun-turn" rel="noopener noreferrer"&gt;Twilio STUN/TURN (A huge part of connecting with WebRTC)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/webrtc/samples" rel="noopener noreferrer"&gt;WebRTC Samples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.wowza.com/blog/webrtc-terminology-and-how-it-works" rel="noopener noreferrer"&gt;How WebRTC works&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Ring Upp - DO Hackathon - Part 3/4 - Final Touches</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Wed, 06 Jan 2021 19:23:17 +0000</pubDate>
      <link>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-3-4-final-touches-1mb6</link>
      <guid>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-3-4-final-touches-1mb6</guid>
      <description>&lt;p&gt;Last post we talked about how Ring Upp was built. Now let's talk about final touch-ups and deploying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Touch-Ups
&lt;/h2&gt;

&lt;p&gt;Only a few things still need to be done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code cleanup

&lt;ul&gt;
&lt;li&gt;Just a little sweeping and polishing. Gotta keep that code clean. I only used Prettier for this project but ESLint and Prettier are usually the go-to.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;README, LICENSE, writing these posts

&lt;ul&gt;
&lt;li&gt;A short README to get anyone started developing with the project. A LICENSE file to say the project is under an MIT license. Then I have to write these posts so I can submit my application to DO Hackathon and everyone can use this app!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Using the app every day

&lt;ul&gt;
&lt;li&gt;To make sure everything works and to find bugs, my brother and I have been using the app for our daily calls. This has been extremely valuable because we tested on Windows, Mac, iOS, Firefox, Chrome, and Safari which exposed several bugs. I can't stress enough how valuable it is to use your software every day and to have something that solves a problem you have.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Deploying (Below)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deploying
&lt;/h2&gt;

&lt;p&gt;Alright now here's what the DO Hackathon is all about: Deploying my awesome app to a platform that will allow me to focus exclusively on my app.&lt;/p&gt;

&lt;p&gt;And how did DigitalOcean App Platform work? Very well and on-par with my experience on other platforms.&lt;/p&gt;

&lt;p&gt;For this project, I am mainly comparing my experience with App Platform to Heroku. While developing and testing Ring Upp I deployed the application with Heroku since I already had an account setup and I was waiting for the complimentary $50 credits from the hackathon.&lt;/p&gt;

&lt;p&gt;This was fine until I was into the final stages of development and I was ready to take on the challenge of moving my project over to App Platform. Except it wasn't a challenge. My account was set up and ready with Digital Ocean, I navigated to App Platform, followed the instructions to point App Platform to my GitHub repository, and my application was deployed to Digital Ocean App Platform. &lt;/p&gt;

&lt;p&gt;I had no issues settings up my application and App Platform does a great job onboarding your project onto their platform. Going forward I will be looking at how App Platform handles an application at load and my options for scaling. &lt;/p&gt;

&lt;p&gt;So far I am very happy with App Platform and am excited to start deploying my side projects to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This project has been on my to-do list for a while and would still be on my to-do list if not for this hackathon. I appreciate &lt;a href="http://dev.to/"&gt;Dev.to&lt;/a&gt; and Digital Ocean for putting this hackathon on and the community for all of the fantastic engagement that I've seen so far.&lt;/p&gt;

&lt;p&gt;If you have questions about the project feel free to message me or comment and I'll get back to you.&lt;/p&gt;

&lt;p&gt;If you are thinking about joining the next hackathon, do it! It's a ton of fun and a fantastic way to have a deadline for a small project you've had on your to-do list.&lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Ring Upp - DO Hackathon - Part 2/4 - Building</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Wed, 06 Jan 2021 19:23:04 +0000</pubDate>
      <link>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-2-4-building-117j</link>
      <guid>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-2-4-building-117j</guid>
      <description>&lt;p&gt;Last post we decided what to build. Now let's talk about how to build.&lt;/p&gt;

&lt;p&gt;We built a video chat app that we can separate out into 3 different parts: Backend, User Interface, WebRTC video chat business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;We'll start with the backend because it will be the backbone of our application. Since this is a small app instead of creating a backend and a React frontend (which is my go-to), the project only needs to be a simple Node.js Express app.&lt;/p&gt;

&lt;p&gt;I'm comfortable and familiar with Node.js so this was my first choice but any framework will work for such a simple application.&lt;/p&gt;

&lt;p&gt;The backend should only do two things. Serve our app and use web sockets to start connections in our chat rooms. More on this below.&lt;/p&gt;

&lt;p&gt;One thing to note here, don't start with a blank slate. Pull from a template or walk through a getting started with Express tutorial. There's no reason not to copy someone's starting point and it makes things a lot less scary. A big part of starting side projects is reducing the barrier to entry.&lt;/p&gt;

&lt;h2&gt;
  
  
  User Interface
&lt;/h2&gt;

&lt;p&gt;The user interface is simple except for the actual chat page. What makes the chat page less than simple is that there are multiple features like screen sharing, multiple users, enabling and disabling video and audio, and input selection. All the features and more that are planned complicate the UX so while developing we have to balance usability and features.&lt;/p&gt;

&lt;p&gt;While the UI/UX can get complicated the way we build them was not. Since this is an Express app we will return the HTML, CSS, and JS when the clients make requests to different endpoints. To simplify the CSS we used Tailwind CSS (my new favorite CSS framework).&lt;/p&gt;

&lt;p&gt;Take a look at the source code for a look at how the pages are handled. They can’t get much simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebRTC video chat business logic
&lt;/h2&gt;

&lt;p&gt;This is the real meat of the application.&lt;/p&gt;

&lt;p&gt;From an extremely high level this is what the chat logic is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client joins a "Room" and opens a web socket to the server&lt;/li&gt;
&lt;li&gt;Another client joins a "Room" and notifies the server of the join&lt;/li&gt;
&lt;li&gt;The server then tells both clients to start a connection with each other&lt;/li&gt;
&lt;li&gt;Clients connect using &lt;a href="https://www.twilio.com/stun-turn"&gt;Twilio's STUN capabilities for WebRTC&lt;/a&gt;. (I'll put some good articles about WebRTC and how/why this connection happens)&lt;/li&gt;
&lt;li&gt;Clients are now connected and a room can accept one more connection. The server will then say the room is "full"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To implement this there was a lot of looking through other implementations. WebRTC has a "samples" repo on GitHub that I &lt;em&gt;highly&lt;/em&gt; recommend you take a look at.&lt;/p&gt;

&lt;p&gt;This also took &lt;em&gt;a lot&lt;/em&gt; of trial and error, testing with multiple users, multiple browsers, and remote connections. The application is still not perfect. The main problem I am still having is reconnecting after connection issues but this is a great MVP.&lt;/p&gt;

&lt;p&gt;For more information on how this works please look at the source code and check out these links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twilio.com/stun-turn"&gt;Twilio STUN/TURN (A huge part of connecting with WebRTC)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/webrtc/samples"&gt;WebRTC Samples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.wowza.com/blog/webrtc-terminology-and-how-it-works"&gt;How WebRTC works&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would love to go into more detail about WebRTC but that will have to be another series.&lt;/p&gt;

&lt;p&gt;Next post let's talk about finishing touches and deploying.&lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Ring Upp - DO Hackathon - Part 1/4 - First Steps</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Wed, 06 Jan 2021 19:22:52 +0000</pubDate>
      <link>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-1-4-first-steps-2li6</link>
      <guid>https://dev.to/craigaholliday/ring-upp-do-hackathon-part-1-4-first-steps-2li6</guid>
      <description>&lt;p&gt;First off, I was super excited to have an excuse to work on a side project with a deadline and an end goal. As well as have a chance to try hosting my project on DigitalOcean App Platform.&lt;/p&gt;

&lt;p&gt;Usually taking time to work on a side project is difficult because the project may be fun but not have a clear way to make money or a project may have a way to make money/be successful but then can feel like regular work.&lt;/p&gt;

&lt;p&gt;This is a great balance between working on something I enjoy and being able to share with the community and also win a contest.&lt;/p&gt;

&lt;p&gt;Now to the first steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  First steps
&lt;/h2&gt;

&lt;p&gt;What to work on? So many projects so little time.&lt;/p&gt;

&lt;p&gt;Three projects came to mind for this contest.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Covid related dashboard or something related to tracking helpful covid data.&lt;/li&gt;
&lt;li&gt;A QA app to track test cases in test suites to be run by QA engineers.&lt;/li&gt;
&lt;li&gt;A video chat app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The covid dashboard would be an interesting project to work on, but with a short timeline, it's not something I would want to start. It would take more time to research and more effort than I could give right now.&lt;/p&gt;

&lt;p&gt;The QA application is something that has been on my list for a while. I had previously built an MVP that works well enough to build user stories and run through tests. Unfortunately, I built it 2 years ago and know so much more about development and what I would want out of the QA project that I may as well rewrite the entire application. This is a useful application that is on my list but once again would take too much time.&lt;/p&gt;

&lt;p&gt;So that leaves the video chat app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The video chat app
&lt;/h2&gt;

&lt;p&gt;I am a Development Manager and Video Engineer as my full-time job and love working on video applications. On my list for a long time is a video application using WebRTC.&lt;/p&gt;

&lt;p&gt;A few months ago I listened to an episode of &lt;a href="https://syntax.fm/show/256/webrtc-and-peer-to-peer-video-calling-with-ian-ramzy"&gt;Syntax.fm&lt;/a&gt; that interviewed a developer talking about a simple video chat application they built. It is a great episode about learning new technology and building a simple app while learning. That along with the changing landscape of video moving towards WebRTC made this a great application to build right now.&lt;/p&gt;

&lt;p&gt;So that's what I set out to build! Oh also the app won't just be between peers it will be between a max of three. So added a bit more of a challenge there.&lt;/p&gt;

&lt;p&gt;Let's lay out what we need for the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Landing page&lt;/li&gt;
&lt;li&gt;A page to create a new call&lt;/li&gt;
&lt;li&gt;A page for the video chat to take place&lt;/li&gt;
&lt;li&gt;Pages to direct unsupported browsers to&lt;/li&gt;
&lt;li&gt;All of the business logic of connecting users with WebRTC and keeping them connected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I won't go too deep into every part of every feature. But in my next post, I'll give some high-level overviews of everything listed above.&lt;/p&gt;

</description>
      <category>dohackathon</category>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to achieve Zen in VS Code</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Wed, 25 Nov 2020 18:24:02 +0000</pubDate>
      <link>https://dev.to/craigaholliday/how-to-achieve-zen-in-vs-code-2fpg</link>
      <guid>https://dev.to/craigaholliday/how-to-achieve-zen-in-vs-code-2fpg</guid>
      <description>&lt;p&gt;You're staring at VS Code, and in front of you is this cluttered mess with random things everywhere that no-one could ever make sense of. But enough about your code, let's talk about how we can make VS Code look &lt;em&gt;so clean&lt;/em&gt; to help us achieve &lt;em&gt;true Zen&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To start, let's go through the VS Code user interface and see how we will leverage VS Code's built-in features to hide any part of the interface that will interfere with our Zen.&lt;/p&gt;

&lt;p&gt;Here is a video version of this post if that is more your speed:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0FPeRDiaK7w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code User Interface
&lt;/h2&gt;

&lt;p&gt;The user interface is broken up into 5 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editor&lt;/strong&gt; - The main area to edit your files. You can open as many editors as you like side by side vertically and horizontally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Side Bar&lt;/strong&gt; - Contains different views like the Explorer to assist you while working on your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status Bar&lt;/strong&gt; - Information about the opened project and the files you edit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activity Bar&lt;/strong&gt; - Located on the far left-hand side, this lets you switch between views and gives you additional context-specific indicators, like the number of outgoing changes when Git is enabled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Panels&lt;/strong&gt; - You can display different panels below the editor region for output or debug information, errors and warnings, or an integrated terminal. Panel can also be moved to the right for more vertical space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5grnovtpow1gekqawid5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5grnovtpow1gekqawid5.png" alt="vs code user interface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VS Code has a ton of different panels, bars, and groups because VS Code can do so many things!&lt;/p&gt;

&lt;p&gt;We will take a look at hiding these parts one by one but first let's look at a feature of VS Code that will hide everything except the editor, called &lt;em&gt;Zen Mode.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Zen Mode
&lt;/h2&gt;

&lt;p&gt;From the VS Code docs, "Zen Mode lets you focus on your code by hiding all UI except the editor (no Activity Bar, Status Bar, Side Bar and Panel), going to full screen and centering the editor layout."&lt;/p&gt;

&lt;p&gt;Zen Mode in VS Code looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl6pgjz5bw3qwo57pjmt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl6pgjz5bw3qwo57pjmt1.png" alt="vs code's default zen mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a great built-in feature that also allows us to customize this mode to our liking.&lt;/p&gt;

&lt;p&gt;Some recommended tweaks would be to disable making VS Code fullscreen and disable centering the layout. This way you can be in Zen Mode and still control the size and position of your VS Code window.&lt;/p&gt;

&lt;p&gt;You can disable fullscreen and center layout by adding the following to your &lt;code&gt;settings.json&lt;/code&gt; by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;Preferences: Open Settings (JSON)&lt;/em&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="nl"&gt;"zenMode.fullScreen"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"zenMode.centerLayout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can open the UI for settings by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;Preferences: Open Settings (UI)&lt;/em&gt; and searching for "Zen Mode" to uncheck those two options.&lt;/p&gt;

&lt;p&gt;With Zen Mode and a couple of custom configurations, we are 90% of the way to our ultimate goal of a completely zen VS Code experience.&lt;/p&gt;

&lt;p&gt;Before we make the last 10% let's go over what is hidden when we toggle Zen Mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does Zen Mode hide?
&lt;/h2&gt;

&lt;p&gt;By default, Zen Mode hides every part of the user interface except the Editor. Let go through each part and how you can hide them yourself without toggling Zen Mode. This can be helpful if you just need one or two parts of the user interface out of your way instead of everything but the editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Activity Bar and Side Bar
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjrlqgasanhkctx2pjbc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjrlqgasanhkctx2pjbc6.png" alt="vs code user interface with activity bar and side bar highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are the two parts on the left of the user interface.&lt;/p&gt;

&lt;p&gt;The Activity Bar can be hidden by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;View: Toggle Activity Bar Visibility.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is not a default keyboard shortcut set but you can always set one that works for you.&lt;/p&gt;

&lt;p&gt;The Side Bar can be hidden by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;View: Toggle Side Bar Visibility.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The default keyboard shortcut for this is &lt;code&gt;cmd + b&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Panel and Status Bar
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F515suoaslghglkn6yaqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F515suoaslghglkn6yaqv.png" alt="vs code user interface with panel and status bar highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are the two parts at the bottom of the user interface.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Panel&lt;/em&gt; can be hidden by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;View: Toggle Panel.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The default keyboard shortcut for this is &lt;code&gt;cmd + j&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Status Bar&lt;/em&gt; can be hidden by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;View: Toggle Status Bar Visibility.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is not a default keyboard shortcut.&lt;/p&gt;

&lt;h2&gt;
  
  
  The last 10% to zen
&lt;/h2&gt;

&lt;p&gt;The default Zen Mode has us 90% of the way to complete Zen but there are a few user interface elements that are still in our way.&lt;/p&gt;

&lt;p&gt;Those elements are the &lt;em&gt;Minimap&lt;/em&gt; and &lt;em&gt;Indent Guides.&lt;/em&gt; So let's look at how to hide them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minimap
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyze7i69o58o1hly02u3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyze7i69o58o1hly02u3w.png" alt="vs code user interface with minimap highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Minimap&lt;/em&gt; is inside the editor part on the right-hand side and gives a zoomed-out look of the file you have open.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Minimap&lt;/em&gt; can be hidden by running the command (&lt;code&gt;cmd + shift + p&lt;/code&gt;) &lt;em&gt;View: Toggle Minimap.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is not a default keyboard shortcut.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indent Guides
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1xjg5dql3yqdrkjybk1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1xjg5dql3yqdrkjybk1a.png" alt="vs code user interface with indent guides highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Indent Guides&lt;/em&gt; are thin vertical lines that show an indent in your file.&lt;/p&gt;

&lt;p&gt;Unfortunately, these still show up in the default Zen Mode because they have to be disabled in settings like this &lt;code&gt;"editor.renderIndentGuides": false,&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We don't want them off all the time so we will need a way to toggle the &lt;em&gt;Minimap&lt;/em&gt; and &lt;em&gt;Indent Guides&lt;/em&gt; when going into Zen Mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Toggle Minimap and Indent Guides
&lt;/h3&gt;

&lt;p&gt;To be able to toggle the &lt;em&gt;Minimap&lt;/em&gt; and &lt;em&gt;Indent Guides&lt;/em&gt; when we toggle Zen Mode we will have to install two extensions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=hoovercj.vscode-settings-cycler" rel="noopener noreferrer"&gt;Settings Cycler&lt;/a&gt; and &lt;a href="https://marketplace.visualstudio.com/items?itemName=ryuta46.multi-command" rel="noopener noreferrer"&gt;multi-command&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These allow us to set up settings to toggle and give us the ability to run multiple commands with one keybinding.&lt;/p&gt;

&lt;p&gt;To oversimplify these steps, after you install these two extensions you can add this snippet to your &lt;code&gt;settings.json&lt;/code&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;multiCommand&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"multiCommand.commands"&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;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"multiCommand.betterZenMode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sequence"&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;"workbench.action.toggleZenMode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="s2"&gt;"settings.cycle.zenModeExtras"&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;span class="p"&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;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cycle&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"settings.cycle"&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;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"zenModeExtras"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"values"&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;span class="nl"&gt;"editor.lineNumbers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"editor.folding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"editor.renderIndentGuides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"editor.minimap.enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;span class="nl"&gt;"editor.lineNumbers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"on"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"editor.folding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"editor.renderIndentGuides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"editor.minimap.enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this snippet to your &lt;code&gt;keybindings.json&lt;/code&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cmd+k z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"extension.multiCommand.execute"&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;"args"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"multiCommand.betterZenMode"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion: A Better Zen Mode
&lt;/h2&gt;

&lt;p&gt;With everything set up, when we use the keybinding &lt;code&gt;cmd + k z&lt;/code&gt; our VS Code editor will go into our new &lt;em&gt;Better Zen Mode&lt;/em&gt; that looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxjt0lwvyz8qa8d8qtrqo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxjt0lwvyz8qa8d8qtrqo.png" alt="vs code custom zen mode or better zen mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Combining the current Zen Mode and our custom configurations we can achieve complete zen when viewing our code. Making the code look good, we will leave to you.&lt;/p&gt;

&lt;p&gt;And here is a comparison of the normal editor, Zen Mode editor, and our Better Zen Mode editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fykjw3yjz77glrlhuhxir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fykjw3yjz77glrlhuhxir.png" alt="comparison between normal, zen mode, and the new custom better zen mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🌟 Thanks! 🌟
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! Let me know what you think of this &lt;em&gt;Better Zen Mode&lt;/em&gt; and any tips you have around making VS Code look great.&lt;/p&gt;

&lt;p&gt;You can follow me on Twitter if you're looking for some more content: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/TheMrHolliday" rel="noopener noreferrer"&gt;https://twitter.com/TheMrHolliday&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a blog is more your thing here is that as well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://koalatea.io/" rel="noopener noreferrer"&gt;https://koalatea.io/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A TON of VS Code tips for productivity</title>
      <dc:creator>Craig Holliday</dc:creator>
      <pubDate>Tue, 10 Nov 2020 17:03:30 +0000</pubDate>
      <link>https://dev.to/craigaholliday/a-ton-of-vs-code-tips-for-productivity-34j3</link>
      <guid>https://dev.to/craigaholliday/a-ton-of-vs-code-tips-for-productivity-34j3</guid>
      <description>&lt;p&gt;Being productive in VS Code can help you focus on just your code or can speed up some repetitive tasks you are doing. To start being productive all you need is to learn a few keyboard shortcuts and install a few extensions.&lt;/p&gt;

&lt;p&gt;So here are some VS Code tips that help me every day.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: This was written for Macs and I would love some help translating this post to work with Windows&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is a video version if that's more your speed:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/9BCJ_BJARH0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was also &lt;a href="https://koalatea.io/a-ton-of-vs-code-tips-for-productivity" rel="noopener noreferrer"&gt;posted on our blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code CLI and the integrated terminal
&lt;/h2&gt;

&lt;h3&gt;
  
  
  VS Code CLI
&lt;/h3&gt;

&lt;p&gt;VSCode has a CLI to open VS Code directly from your terminal.&lt;/p&gt;

&lt;p&gt;Install it with these simple steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch VS Code&lt;/li&gt;
&lt;li&gt;Open the Command Palette (&lt;code&gt;shift+cmd+p&lt;/code&gt;) and type 'shell command' to find the Shell Command: Install 'code' command in PATH command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5j33v0pr1f97ge8uucvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5j33v0pr1f97ge8uucvv.png" alt="VS code shell command example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restart the terminal for the new \$PATH value to take effect. You'll be able to type 'code .' in any folder to start editing files in that folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line" rel="noopener noreferrer"&gt;If you're having issues go here to the documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrated Terminal
&lt;/h3&gt;

&lt;p&gt;VS Code has an integrated terminal you can open and start using directly in VS Code. If you didn't know, now you know 💁‍♀️. And you have to start using it.&lt;/p&gt;

&lt;p&gt;It works exactly like your current terminal and you can open it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the ⌃` keyboard shortcut with the backtick character.&lt;/li&gt;
&lt;li&gt;Use the &lt;strong&gt;View&lt;/strong&gt; &amp;gt; &lt;strong&gt;Terminal&lt;/strong&gt; menu command.&lt;/li&gt;
&lt;li&gt;From the &lt;strong&gt;Command Palette&lt;/strong&gt; (&lt;code&gt;shift+cmd+p&lt;/code&gt;), use the &lt;strong&gt;View: Toggle Integrated Terminal&lt;/strong&gt; command.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Refactoring with Rename Symbol
&lt;/h2&gt;

&lt;p&gt;Naming is the hardest and most important part of programming. That's just how it is, I don't make the rules.&lt;/p&gt;

&lt;p&gt;You are going to be renaming a lot while building your Twitter competitor. So let's make that much easier.&lt;/p&gt;

&lt;p&gt;To rename a symbol (in some languages even across multiple files) press &lt;code&gt;F2&lt;/code&gt; after selecting the symbol you would like to rename. Then type away and you just saved yourself 100s of hours (over the course of many many years, of course).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc68tpu0rtuu9hv0f1ehc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc68tpu0rtuu9hv0f1ehc.png" alt="VS code rename symbol example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple selections (multi-cursor)
&lt;/h2&gt;

&lt;p&gt;Now here is the tip that will change your life. Write this down, bookmark it, remember this, or whatever. This is just the best tip and you'll use it all the time.&lt;/p&gt;

&lt;p&gt;Multiple-cursors can be added and operate independently based on the context it sits in.&lt;/p&gt;

&lt;p&gt;So there are a few ways you can add multiple-cursors.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;alt+click&lt;/code&gt; which will add a new cursor on every click.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;alt+cmd+down&lt;/code&gt; or &lt;code&gt;alt+cmd+up&lt;/code&gt; that will insert cursors below or above respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fydog5eoyfa3a2gqm76v5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fydog5eoyfa3a2gqm76v5.gif" alt="Multi-cursor example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cmd+d&lt;/code&gt; selects the word at the cursor or the next occurrence of the current selection adding a cursor at each word.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shift+cmd+l&lt;/code&gt; will select each occurrence of the currently selected text adding a cursor to each selection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo1itr4heqy1y5ozgrazu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo1itr4heqy1y5ozgrazu.gif" alt="Multi-cursor by word example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also check out the &lt;a href="https://marketplace.visualstudio.com/items?itemName=bigous.vscode-multi-line-tricks" rel="noopener noreferrer"&gt;Multi Line tricks extension&lt;/a&gt; which will allow you to add a cursor at the end of each selected line with &lt;code&gt;alt+shift+l&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Command Palette
&lt;/h2&gt;

&lt;p&gt;VS Code's command palette makes VS Code completely accessible using only the keyboard. Typing &lt;code&gt;shift+cmd+P&lt;/code&gt; will bring up the Command Palette allowing you to access all of the functionality of VS Code.&lt;/p&gt;

&lt;p&gt;Here are a few shortcuts for the most useful commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cmd+P&lt;/code&gt; will let you navigate to any file or symbol by typing its name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl+tab&lt;/code&gt; will cycle you through the last set of files opened&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+cmd+P&lt;/code&gt; will bring you directly to the editor commands&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+cmd+O&lt;/code&gt; will let you navigate to a specific symbol in a file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alt+G&lt;/code&gt; will let you navigate to a specific line in a file&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  User Interface Navigation
&lt;/h2&gt;

&lt;p&gt;The user interface is broken up into 5 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editor&lt;/strong&gt; - The main area to edit your files. You can open as many editors as you like side by side vertically and horizontally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Side Bar&lt;/strong&gt; - Contains different views like the Explorer to assist you while working on your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status Bar&lt;/strong&gt; - Information about the opened project and the files you edit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activity Bar&lt;/strong&gt; - Located on the far left-hand side, this lets you switch between views and gives you additional context-specific indicators, like the number of outgoing changes when Git is enabled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Panels&lt;/strong&gt; - You can display different panels below the editor region for output or debug information, errors and warnings, or an integrated terminal. Panel can also be moved to the right for more vertical space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhrvv8kowuo95yu2qmizf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhrvv8kowuo95yu2qmizf.png" alt="VS code UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some shortcuts to help you navigate the UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;shift+cmd+E&lt;/code&gt; Explorer (A)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+cmd+F&lt;/code&gt; Search (A)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+ctrl+G&lt;/code&gt; Source Control (A)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+shift+D&lt;/code&gt; Run Panel (A)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+shift+X&lt;/code&gt; Extension Panel (A)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+b&lt;/code&gt; Toggle Side Bar visibility (B)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl+cmd+w&lt;/code&gt; Toggle Tab visibility (C)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+j&lt;/code&gt; Toggle open bottom panel (D) with Terminal, Problems, Output, Debug Console&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  More Keyboard Shortcuts
&lt;/h2&gt;

&lt;p&gt;There are a ton of keyboard shortcuts available in VS Code. We'll go over some general shortcuts now and more detailed tips for each feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  General
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alt+Z&lt;/code&gt; Toggle word wrap. If you have long lines in your file and need to see everything without formatting each line.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+F&lt;/code&gt; Search in the current file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alt+shift+left&lt;/code&gt; / &lt;code&gt;alt+shift+right&lt;/code&gt; Make selection by word&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+D&lt;/code&gt; Finds and selects the next match for the currently selected word.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+down&lt;/code&gt; / &lt;code&gt;cmd+up&lt;/code&gt; Move cursor to end/beginning of the current file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+left&lt;/code&gt; / &lt;code&gt;cmd+right&lt;/code&gt; Move cursor to end/beginning of current line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alt+left&lt;/code&gt; / &lt;code&gt;alt+right&lt;/code&gt; Move cursor by word&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl+-&lt;/code&gt; / &lt;code&gt;ctrl+shift+-&lt;/code&gt; &lt;em&gt;Go back&lt;/em&gt; and &lt;em&gt;Go forward&lt;/em&gt;. This is across files and selections. So if you move files you can go back forward. If you go to the bottom of a file and make a selection you can &lt;em&gt;Go back to your previous selection.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+ctrl+cmd+left&lt;/code&gt; / &lt;code&gt;shift+ctrl+cmd+right&lt;/code&gt; Expand or shrink block selection. This is useful for selecting a component, function, HTML element, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F12&lt;/code&gt; / &lt;code&gt;cmd+click&lt;/code&gt; Jump to definition&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Editing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cmd+X&lt;/code&gt; When not selecting text will cut the current line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd+shift+K&lt;/code&gt; Delete current line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+down&lt;/code&gt; / &lt;code&gt;shift+up&lt;/code&gt; Move a selection up or down.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alt+down&lt;/code&gt; / &lt;code&gt;alt+up&lt;/code&gt; Move a line up or down.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift+alt+down&lt;/code&gt; / &lt;code&gt;shift+alt+up&lt;/code&gt; Copy line or selection and paste below or above line or selection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=bigous.vscode-multi-line-tricks" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=bigous.vscode-multi-line-tricks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.vscodecandothat.com/" rel="noopener noreferrer"&gt;https://www.vscodecandothat.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.xiaoru.li/post/vscode-tricks/" rel="noopener noreferrer"&gt;https://www.xiaoru.li/post/vscode-tricks/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.telerik.com/blogs/7-vs-code-productivity-hacks-17-extensions-that-will-change-your-life" rel="noopener noreferrer"&gt;https://www.telerik.com/blogs/7-vs-code-productivity-hacks-17-extensions-that-will-change-your-life&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/getstarted/tips-and-tricks" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/getstarted/tips-and-tricks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mokkapps/how-i-increased-my-productivity-with-visual-studio-code-gfo"&gt;https://dev.to/mokkapps/how-i-increased-my-productivity-with-visual-studio-code-gfo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/editor/codebasics#_multiple-selections-multicursor" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/editor/codebasics#_multiple-selections-multicursor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/editor/integrated-terminal" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/editor/integrated-terminal&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/getstarted/userinterface" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/getstarted/userinterface&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
