<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: James Foran</title>
    <description>The latest articles on Forem by James Foran (@james_foran).</description>
    <link>https://forem.com/james_foran</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%2F460323%2Fb42861b8-1c07-4996-824b-c05349d29b68.jpeg</url>
      <title>Forem: James Foran</title>
      <link>https://forem.com/james_foran</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/james_foran"/>
    <language>en</language>
    <item>
      <title>Vue Transition Group: Strange Entry behaviour</title>
      <dc:creator>James Foran</dc:creator>
      <pubDate>Wed, 09 Dec 2020 10:17:06 +0000</pubDate>
      <link>https://forem.com/james_foran/vue-transition-group-strange-entry-behaviour-1agi</link>
      <guid>https://forem.com/james_foran/vue-transition-group-strange-entry-behaviour-1agi</guid>
      <description>&lt;p&gt;While working with Vue's transition-group API today I was getting a strange entry motion on an element which I was adding to a transition-group. It seemed to be entering from the top-left of the screen when the item was added, however, it would leave the screen as I was expecting it too (as per the CSS which is shown later).&lt;/p&gt;

&lt;p&gt;The below codepen demonstrates the behaviour I was experiencing...&lt;/p&gt;

&lt;p&gt;Hit "Pull the trigger" to see the behaviour. The second red circle flies in from the left, rather than sliding in from the right!&lt;/p&gt;

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

&lt;p&gt;My CSS is set to bring the second circle in from the right, and have it leave to the right once it's removed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.smoothFlex-enter&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.smoothFlex-leave-to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It appeared as if the &lt;code&gt;smoothFlex-enter&lt;/code&gt; class was not being applied to the element at the start of the animation, causing it to fly in from afar!&lt;/p&gt;

&lt;p&gt;On further inspection via the dev tools, I noticed that after the element had been "removed" from the list, remained with an inline style of &lt;code&gt;display:none&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"circle smoothFlex-enter-to smoothFlex-move"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display: none;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above inline Style is added by Vue when the &lt;code&gt;v-show&lt;/code&gt; directive evaluates to &lt;code&gt;false&lt;/code&gt;. I was hopeful now that I had found the issue... Switching to &lt;code&gt;v-if&lt;/code&gt; resolved the issue immediately!&lt;/p&gt;

&lt;p&gt;In the codepen above, select "fix me" to see the desired behaviour in action. This button just switches out the &lt;code&gt;v-show&lt;/code&gt; example for a &lt;code&gt;v-if&lt;/code&gt; example.&lt;/p&gt;

&lt;p&gt;I hope you have found this post useful!&lt;/p&gt;

&lt;p&gt;Head over and have a read of the Vue docs for more information on the transition-group API. It's pretty amazing, but as always, it can be quite frustrating when things don't work as expected!&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://vuejs.org/v2/guide/transitions.html#List-Transitions"&gt;vue animations&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>css</category>
      <category>html</category>
    </item>
    <item>
      <title>Vue/Nuxt + ChakraUI: Tabs</title>
      <dc:creator>James Foran</dc:creator>
      <pubDate>Mon, 07 Dec 2020 04:08:08 +0000</pubDate>
      <link>https://forem.com/james_foran/vue-nuxt-chakraui-tabs-3ll5</link>
      <guid>https://forem.com/james_foran/vue-nuxt-chakraui-tabs-3ll5</guid>
      <description>&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%2Fmgvh8h79eq3kk6wxr1d3.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%2Fmgvh8h79eq3kk6wxr1d3.png" alt="Chakra UI logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have been working with Chakra UI Vue for several months. I am using Chakra in a side project to learn more about JAMStack and Vue/Nuxt. I am drawn to Chakra UI because of its practical set of components, and its focus on accessibility. This is the first article in a series I will be publishing about Vue and Chakra. I hope you enjoy!&lt;/p&gt;

&lt;p&gt;One of the components I have been working with a lot is the tabs component. Tabs works well when presenting content. I have also been using it to driver high-level option selection for specific processes and user flows. Let's jump right in...&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post assumes you already have a Nuxt project setup with Chakra installed, as well as auto-imports enabled.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;The standard way of setting up tabs using Chakra is using a parent &lt;code&gt;c-tabs&lt;/code&gt; element, containing a single &lt;code&gt;c-tab-list&lt;/code&gt; and single &lt;code&gt;c-tab-panels&lt;/code&gt; element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-box&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c-tabs&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab-list&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab&amp;gt;&lt;/span&gt;One&lt;span class="nt"&gt;&amp;lt;/c-tab&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab&amp;gt;&lt;/span&gt;Two&lt;span class="nt"&gt;&amp;lt;/c-tab&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab&amp;gt;&lt;/span&gt;Three&lt;span class="nt"&gt;&amp;lt;/c-tab&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c-tab-list&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab-panels&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab-panel&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;one!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c-tab-panel&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab-panel&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;two!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c-tab-panel&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab-panel&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;three!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c-tab-panel&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c-tab-panels&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/c-tabs&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/c-box&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important to ensure you have the same number of &lt;code&gt;c-tab-panel&lt;/code&gt; elements as you do &lt;code&gt;c-tab&lt;/code&gt; elements. Not doing so may mean your content is not accessible to the user. The order is also critical to this working, as the first &lt;code&gt;c-tab&lt;/code&gt; button will correspond to the first &lt;code&gt;c-tab-panel&lt;/code&gt; element. This is quick to get up and running. Note, each &lt;code&gt;c-tab&lt;/code&gt; becomes a button when it renders.&lt;/p&gt;

&lt;p&gt;In addition to the separation of content, I also want to know which tab a user has selected. To do this I recommend moving to a different pattern. This pattern involves moving the tab options to an array and then using Vues &lt;code&gt;v-for&lt;/code&gt; directive look to generate the &lt;code&gt;c-tab-list&lt;/code&gt; elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-box&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;c-tabs&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab-list&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;c-tab&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"tab in tabs"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"tab"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{
            tab
          }}&lt;span class="nt"&gt;&amp;lt;/c-tab&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/c-tab-list&amp;gt;&lt;/span&gt;
...
    &lt;span class="nt"&gt;&amp;lt;/c-tabs&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/c-box&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have now introduced a new data object here.. &lt;code&gt;tabs&lt;/code&gt;. Lets set it up so the above code works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;data&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="na"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;One&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Three&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;tabIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then call a method on the &lt;code&gt;@change&lt;/code&gt; event, to change the tabIndex value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tabs&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"setTabIndex"&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;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab-list&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;...

...
methods: &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTabIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As things are now, &lt;code&gt;tabIndex&lt;/code&gt; will change as the user selects a different tab, but we don't yet know which option the user has selected, just its index value. To may the index value, back to the array, we then use a computed property to give us the selected tab text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;selectedTab&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have the &lt;code&gt;selectedTab&lt;/code&gt;, and &lt;code&gt;tabIndex&lt;/code&gt; values in the parent component, which we can used to drive other behaviour.&lt;/p&gt;

&lt;p&gt;For one final feature, we can then drive the default index, property in the c-tabs element using the tabIndex field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;c-tabs&lt;/span&gt; &lt;span class="na"&gt;:default-index=&lt;/span&gt;&lt;span class="s"&gt;"tabIndex"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"setTabIndex"&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;By doing this, you can set the initial tab selection. &lt;/p&gt;

&lt;h1&gt;
  
  
  Limitations of this approach
&lt;/h1&gt;

&lt;p&gt;Your c-tab styling needs to be simple. Adding images or icons to your tab may over-complicate things. When using library components like this, keep it simple.&lt;/p&gt;

&lt;p&gt;Another limitation may present itself if you want to enable/disable a tab. In this case, the following pattern works better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative
&lt;/h2&gt;

&lt;p&gt;To enable a  single tab to be disabled, the following approach can be applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab-list&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;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab&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;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;is-disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tabTwoDisabled"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab&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;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab&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;c&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;tab-list&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nf"&gt;data&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="na"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;One&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Three&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;tabIndex&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="na"&gt;tabTwoDisabled&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="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This maintains the array of options, but gives the programmer the ability to enable/disable a single tab.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Chakra's tabs are a joy to work with, as long as you keep it simple. If you also want to know the current active tab, then the above pattern works well. &lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vue.chakra-ui.com/tabs" rel="noopener noreferrer"&gt;Chakra ui - tabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vue.chakra-ui.com/auto-import-components" rel="noopener noreferrer"&gt;Chakra ui - auto imports&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>nuxt</category>
      <category>chakra</category>
    </item>
    <item>
      <title>A tale of two database paradigms </title>
      <dc:creator>James Foran</dc:creator>
      <pubDate>Tue, 08 Sep 2020 11:24:10 +0000</pubDate>
      <link>https://forem.com/james_foran/a-tale-of-two-database-paradigms-1f32</link>
      <guid>https://forem.com/james_foran/a-tale-of-two-database-paradigms-1f32</guid>
      <description>&lt;p&gt;It was the best of times, it was the worst of times. It was the age of wisdom, it was the age of foolishness. And I need a database for my front end. &lt;/p&gt;

&lt;p&gt;There are many solutions out there for this exact problem. Having worked with SQL databases for most of my career, I am very comfortable with relational databases, SQL scripts, PL/SQL, all that jazz. But the world of front end development is relatively new to me. &lt;/p&gt;

&lt;p&gt;Currently I am developing a web application that will change the world! t the very least it is changing my perception of the world, and helping me learn the ins and outs of VueJS, Nuxt, Netlify functions, and now, databases for the front end! &lt;/p&gt;

&lt;p&gt;Having recently done some prototyping with Netlify functions, I am really excited at the prospects of building out lambda functions using Node.js, to provide my frontend with the data it needs. &lt;/p&gt;

&lt;p&gt;Perhaps suffering from shiny ball syndrome, I dove straight into FaunaDB. Initial prototyping did not even need netlify functions. I was able to get up and running with a noSQL database and GraphQL interface in one fell swoop. It really was quite a simple process, and the performance of my graphQL queries were fast, sub 100ms repeatedly. However, I quickly ran into some constraints, that I was not well equipped to overcome quickly.&lt;/p&gt;

&lt;p&gt;My history of solving problems with SQL left me struggling with GraphQL as a way to access data. . I am used to being able to shape my data in an SQL script, and filter, manipulate, all in the one place. Working with GraphQL data I was really restricted with this way of thinking. Sticking with FaunaDB, I turned to the native Fauna Query Language. This was completely foreign to me, but I felt if I spent some time trying to learn it, I could really benefit.&lt;/p&gt;

&lt;p&gt;FQL is a procedural language, while SQL is declarative. The procedural nature of FQL means that all the complexities of executing a query are front and centre when your write your very first query. Keen to learn though, I gave myself a weekend. My first target was to convert at simple SQL query, joining two tables(aka collections), and restrict the data based on a parameters in each table. In SQL, this is a 20 second query to write. This is something that cannot done in a GraphQL query, and as I found out, is not straight forward in FaunaDB either.&lt;/p&gt;

&lt;p&gt;To do so, you have to create indexes on the data fields you want to query on, and the resulting FQL is really foreign to me. So foreign to me, I could not get my head around it in a weekend. At this point, I realised I was not yet ready for a dive into noSQL databases. They were really going to slow me down. &lt;/p&gt;

&lt;p&gt;In the future, when I do have the time and/or the need for a noSQL database, I think I will start with &lt;a href="https://www.dynamodbbook.com/"&gt;dynamodbbook&lt;/a&gt;. There is a great podcast interview with the author of the book Alex DeBrie on &lt;a href="https://softwareengineeringdaily.com/2020/07/02/dynamodb-with-alex-debrie/"&gt;Sofware Engineering Daily podcast.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I began to look elsewhere. What were others doing in the JAMStack space? At the time #RedwoodJS was being launched, and Tom Preston-Warner was doing the rounds on many of the JS podcasts I listen to. They too had decided to steer away from FaunaDB, and were instead building their full stack JAMStack using &lt;code&gt;postgres&lt;/code&gt; and &lt;code&gt;Prisma.io&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Postgres, an SQL database... now that is a language I am familiar with... and open source also. But what is Prisma.io? I decided to find out if it could give me what I needed in my Netlify functions...&lt;/p&gt;

&lt;p&gt;So away I went, starting with my familiar SQL database table creation. Comparing this process alone to working with FaunaDB, I would say the process of generating a FaunaDB GraphQL schema is actually easier, and a bit more streamline, however, its the next step that really blew my mind with Prisma.io...&lt;/p&gt;

&lt;p&gt;Different to many of the &lt;a href="https://en.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM's&lt;/a&gt; the Prisma CLI has a function call &lt;code&gt;introspect&lt;/code&gt;. This basically looks at your database, and automatically builds the application model. From here, you need to execute a second function (what a pain!) call &lt;code&gt;generate&lt;/code&gt; and you are ready to go. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;generate&lt;/code&gt; command, and I will take this straight from the prisma.io documentation, &lt;em&gt;"provides a programmatic and type-safe API to read and write data in the shape of your application models"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Within a few hours, I was already feeling very comfortable with the API's, and actually felt quite powerful. The API's are a direct match for the relational data models, and I am able to do most things I can do using SQL, however, I am using JavaScript, and benefiting from the type-safe API's at the same time. And if i run into limitations, I can simply write an SQL Script, and execute it using a Prisma API&lt;/p&gt;

&lt;p&gt;So, for now, I think I will stay in the familiar city of SQL.. I am still really keen to learn more about noSQL, and FaunaDB. I biggest hope for FaunaDB is that they come up with an API similar to prisma, which abstracts away come of the complexities of FQL. SQL is on the road-map for FaunaDB.. I will definitely be watching this space.&lt;/p&gt;

</description>
      <category>prisma</category>
      <category>postgres</category>
      <category>fauna</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Perfect Documentation</title>
      <dc:creator>James Foran</dc:creator>
      <pubDate>Wed, 02 Sep 2020 02:58:00 +0000</pubDate>
      <link>https://forem.com/james_foran/perfect-documentation-12la</link>
      <guid>https://forem.com/james_foran/perfect-documentation-12la</guid>
      <description>&lt;p&gt;So you have taken the bait. Documentation really is the hottest topic in tech right now 😼.&lt;/p&gt;

&lt;p&gt;This post is inspired by the podcast &lt;a href="https://enjoythevue.io/"&gt;Enjoy the Vue&lt;/a&gt; where they discussed in detail the documentation process. Check out [episode 30(&lt;a href="https://enjoythevue.io/episodes/30"&gt;https://enjoythevue.io/episodes/30&lt;/a&gt;) for all the gory details! Thanks &lt;a href="https://twitter.com/n_tepluhina"&gt;Natalia&lt;/a&gt; and &lt;a href="https://www.instagram.com/mxsambrandt/"&gt;Sam&lt;/a&gt; and the rest of the team at Enjoy the Vue! Now lets dig in to this very high level process 😜.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Process
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hh2TlYAN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xkcl5qp3vksbj5t80tfa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hh2TlYAN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xkcl5qp3vksbj5t80tfa.jpg" alt="Documentation Process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Crap Documentation (docs)
&lt;/h2&gt;

&lt;p&gt;You have to start somewhere.. and documentation will always be less than ideal to begin with. There are no shortcuts too good documentation either. Don't expect your first draft to be close to good. Just do it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Review
&lt;/h2&gt;

&lt;p&gt;After you have completed your personal review, you need the documentation to be reviewed by others. This will include SME's (subject matter experts) and people who represent the intended audience. If you don't have people available to review it, publish it. You can then incorporate feedback from readers feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good Documentation
&lt;/h2&gt;

&lt;p&gt;After many reviews, and feedback from readers, documentation can get to a good state. Be careful though, this will not last. As time passes, documentation can quickly become outdated, and will become crap documentation again in no time. &lt;/p&gt;

&lt;h2&gt;
  
  
  Perfect Documentation
&lt;/h2&gt;

&lt;p&gt;While its an honorable goal, no documentation will ever be perfect. Maintaining good documentation is a lot of work in itself. But the benefits of maintaining good documentation are huge. &lt;/p&gt;

&lt;p&gt;I think much of the success of VueJS today has to do with its great documentation. Yes, its great, and that is because there are so many contributors. Over 700 people have contributed to the Vue docs. &lt;/p&gt;

&lt;p&gt;I think documentation can help in many ways. I also like to document stuff before I start developing in some cases too. It helps me to frame my thoughts, and keeps me focused if I get stuck on a technical issue that takes me down a rabbit 🐰 hole.&lt;/p&gt;

&lt;p&gt;And, this document is in the "crap" phase itself. I would love for you to review it, and provide feedback below. Perhaps together we can make this process "good".&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>development</category>
      <category>vue</category>
    </item>
    <item>
      <title>Netlify functions + custom Utils</title>
      <dc:creator>James Foran</dc:creator>
      <pubDate>Tue, 01 Sep 2020 12:02:27 +0000</pubDate>
      <link>https://forem.com/james_foran/netlify-functions-custom-utils-4k2e</link>
      <guid>https://forem.com/james_foran/netlify-functions-custom-utils-4k2e</guid>
      <description>&lt;h1&gt;
  
  
  In the beginning
&lt;/h1&gt;

&lt;p&gt;Earlier this year I started to experiment with Netlify Functions. I was really excited at how easy the whole process was. However, when I went to use them in a live project I immediately wanted to share some code between functions. Coming coding c++ in Arduino, this was pretty easy. I wanted a similar experience in Node.&lt;/p&gt;

&lt;p&gt;Being new to Node and JavaScript, it took me some time to find the solution that I thought was right for this situation. &lt;/p&gt;

&lt;p&gt;I will take you through the most basic example, starting with a clean slate. The following assumes you have node, npm, and &lt;a href="https://www.netlify.com/products/dev/"&gt;netlify dev&lt;/a&gt; installed in your pc.&lt;/p&gt;

&lt;p&gt;Firstly though, what do I want to achieve. For the project in question, I have several functions that make calls to the Strava API. As part of this, I need to refresh the token. This is not something I wanted to do in each function, so, I needed to create some shared functionality, to ensure my code is DRY. &lt;/p&gt;

&lt;h2&gt;
  
  
  Netlify functions, as simple as can be.
&lt;/h2&gt;

&lt;p&gt;The following &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First lets start a new project. Create a new &lt;code&gt;project&lt;/code&gt; Directory. I have called mine &lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;netlify.toml&lt;/code&gt; file, and a &lt;code&gt;functions&lt;/code&gt; directory within &lt;code&gt;project&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit the &lt;code&gt;netlify.toml&lt;/code&gt; file, and add the following lines&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[build]
    functions = "functions"
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;create a hello-world.js file in the functions directory.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&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;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lets test this quickly. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note, I am using windows terminal with wsl2.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;from the terminal of your project directory (not the function folder), run the command &lt;code&gt;netlify dev&lt;/code&gt;. In a separate terminal, run &lt;code&gt;netlify functions:invoke&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WtS1vOAh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7a7rkctklw90mcvjlgni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WtS1vOAh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7a7rkctklw90mcvjlgni.png" alt="netlify dev function:invoke"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accept the prompts, and you should should now see the function execute. Here is what it looks like for me...&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CeQUHso2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j9175nm63u4zqe3avon2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CeQUHso2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j9175nm63u4zqe3avon2.png" alt="netlify dev function output"&gt;&lt;/a&gt;&lt;br&gt;
In the first terminal, we have the console.log outputs, and in the second, we have the message "hello-world".&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Netlify functions + a utility node module
&lt;/h2&gt;

&lt;p&gt;Hopefully this has all worked out so far for you. If not, keep trying! We are not going to move onto the tricky part, building a node module. Its easier than you might think.&lt;/p&gt;

&lt;p&gt;There are options within NPM to publish a module, but I want to develop side by side for now. Instead, I will create a local 'node module', that we can utilise in our hello-world file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a &lt;code&gt;utils&lt;/code&gt; folder, inside your &lt;code&gt;functions&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;create a&lt;code&gt;package.json&lt;/code&gt; file. This can be done manually, or by running &lt;code&gt;npm init&lt;/code&gt; in the directory. Note the &lt;code&gt;src/index.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm run build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;james@flexion.tech&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;license&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MIT&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;/li&gt;
&lt;li&gt;&lt;p&gt;Now create a &lt;code&gt;src&lt;/code&gt; directory. Within that directory, create an &lt;code&gt;index.js&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy in the following code. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note, we are just using CommonJS modules here.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hello&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello from utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goodbye&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goodbye function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;goodbye from utils&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Next, create a package.json file in the functions directory.. You can again use npm init as we did previously. The most important difference is the following addition:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"utils"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"file:utils"&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;/li&gt;
&lt;li&gt;&lt;p&gt;We are almost ready to put our fuctions to use,  but there is one important last step. From the functions folder, we have to now run &lt;code&gt;npm install&lt;/code&gt;. This is a one time thing only. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lets now update our &lt;code&gt;hello-world.js&lt;/code&gt; file. One thing I like about this, is it does not expose the utility functions, and keeps everything in one place.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;utils&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;utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;goodbye&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goodbye&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;lets &lt;strong&gt;&lt;em&gt;test&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make sure &lt;code&gt;netlify Dev&lt;/code&gt; is running. &lt;/li&gt;
&lt;li&gt;Lets run the function directly this time. this time run &lt;code&gt;netlify functions:invoke hello-world --no-identity&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review the output. You should see the object displayed in the invoke window, and a console.trace output in Netlify Dev&lt;br&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2QYAC-_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cf5ifw11zo09f5x6l2i3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2QYAC-_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cf5ifw11zo09f5x6l2i3.png" alt="netlify dev console.trace"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  that's a wrap...
&lt;/h1&gt;

&lt;p&gt;Thanks for reading. If you found any mistakes, or have some further input, please let me know in the comments. There is also a repo on &lt;a href="https://github.com/JamesForan/netlify-functions-shared-code/tree/step-2"&gt;github&lt;/a&gt; if you want to check it out.&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>javascript</category>
      <category>node</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
