<?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: Ronnie Villarini</title>
    <description>The latest articles on Forem by Ronnie Villarini (@_ronini).</description>
    <link>https://forem.com/_ronini</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%2F138064%2F45604c49-8837-44de-9ae1-4899bb648655.jpeg</url>
      <title>Forem: Ronnie Villarini</title>
      <link>https://forem.com/_ronini</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/_ronini"/>
    <language>en</language>
    <item>
      <title>What Neovim taught me about myself</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Mon, 08 Apr 2024 00:00:00 +0000</pubDate>
      <link>https://forem.com/_ronini/what-neovim-taught-me-about-myself-3heh</link>
      <guid>https://forem.com/_ronini/what-neovim-taught-me-about-myself-3heh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Before we get started, I'm going to say "Vim" a lot in this article. My experience has actually been with Neovim, but most, if not all, of what I have to say here will be applicable to either.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I've been using &lt;a href="https://neovim.io/"&gt;Neovim&lt;/a&gt; for roughly a month now and it has been quite the experience. I've had several moments of almost giving up, I've learned a lot about what makes this tool so special, and, surprisingly, I've learned a lot about myself in the process. I'll get to that towards the end of the post, as it's perhaps a little more philosophical and maybe not what most people will be interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Learning Curve
&lt;/h2&gt;

&lt;p&gt;Everyone has heard about how hard Vim is to learn. The "I can't exit Vim" meme has probably been tired out at this point, and it's true, it is pretty difficult. What only those who seem to get through that learning curve talk about though, is how &lt;strong&gt;worth&lt;/strong&gt; it is. I had heard this a handful of times throughout my career from the few Vim users I encountered, but I never really took it seriously. I do believe that keyboard shortcuts are something everyone should learn, but I didn't really think it would go much further than that.&lt;/p&gt;

&lt;p&gt;I was wrong. I was so, so wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vim Motions
&lt;/h2&gt;

&lt;p&gt;This is the first thing that you'll really learn if you embark on this journey, and it's arguably where the biggest benefit is. The ability to do &lt;em&gt;so&lt;/em&gt; much without ever leaving home row is incredible. As I said before, I've always been a fan of keyboard shortcuts, but Vim takes that to another level. Navigating code without moving my hand awkwardly to the arrow keys (or holding down a modifier key to access the layer where my arrows live on my &lt;a href="https://www.zsa.io/voyager"&gt;ZSA Voyager&lt;/a&gt;), using &lt;code&gt;w&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, or &lt;code&gt;e&lt;/code&gt; to flow through words, &lt;code&gt;f&lt;/code&gt; or &lt;code&gt;t&lt;/code&gt; to jump to (or just before) a specific character... the list goes on. It really is not only more efficient, but also just so much more enjoyable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Efficiency does &lt;strong&gt;not&lt;/strong&gt; always mean speed. You may very well be fast with your mouse or however you navigate your code, but it's undeniable that hitting &lt;code&gt;e&lt;/code&gt; to go to the end of a word is just more &lt;strong&gt;efficient&lt;/strong&gt; than holding down option/alt and tapping the right arrow key.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These motions are just the tip of the iceberg, really. There are so many more and I'm still not &lt;em&gt;quite&lt;/em&gt; to the point where I &lt;strong&gt;never&lt;/strong&gt; have to think about it, but I &lt;em&gt;am&lt;/em&gt; to the point where it's comfortable and navigating in other programs feels clunky and difficult. Honestly, once you get comfortable with the Vim motions, you could probably just stop here. There are Vim modes or plugins in almost any other editing software that will allow you to use them and, like I said before, this is largely the biggest benefit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enjoyment
&lt;/h2&gt;

&lt;p&gt;It's weird to title a section "enjoyment" a few paragraphs after talking about just how difficult or frustrating learning Vim can be. It's true though, it's an absolute blast. In fact, I'd go so far as to say that learning Vim has sparked my love for code again, something that I have really lost over the last year or so while battling chronic feelings of disinterest. Learning Vim was so much fun that I found myself somewhat addicted to it. I watched countless videos, read articles, spent time playing &lt;a href="https://vim-adventures.com"&gt;vim adventures&lt;/a&gt;, and just found myself fully immersed. Not only was I enjoying the process, but I was also enjoying the dopamine hit of &lt;em&gt;learning&lt;/em&gt; and seeing evidence of my improvement as I went from stumbling through the most basic of motions to (seemingly) &lt;em&gt;flying&lt;/em&gt; through my code at work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned about myself
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;This section is going to be very specific to me, my experience, and my own personal growth. If you're not interested in that, feel free to stop here. I really hope you give Vim a shot though, and if you do, please let me know how it goes for you!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hnQHB2h_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExYThycjI5NWNkbWljYjI3ZDl1cjgzNHFqdnY5Ym80a25mMm9jY3I3cCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l0MYEwUrE0ei2BAGc/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hnQHB2h_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExYThycjI5NWNkbWljYjI3ZDl1cjgzNHFqdnY5Ym80a25mMm9jY3I3cCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l0MYEwUrE0ei2BAGc/giphy.gif" alt="A man with a skull reciting the famous 'to be or not to be' line by shakespeare." width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, before I speak about what I learned about myself, I want to share how I even got started on this path.&lt;/p&gt;

&lt;p&gt;A former manager, mentor, and now good friend of mine whom you may know as &lt;a href="https://www.youtube.com/@dreamsofcode"&gt;Dreams of Code&lt;/a&gt;, absolutely blew me away when I used to pair with him. When I started to grow interested in learning, I had a few conversations with him about it and he suggested Vim Adventures. I played through the first few levels, but it wasn't really clicking for me. I was mildly interested at best. I did change the arrow keys on my keyboard to be on a layer under &lt;code&gt;h,j,k,l&lt;/code&gt; as opposed to the &lt;code&gt;i,j,k,l&lt;/code&gt; that I had been using, but that was about as far as I got for several months after.&lt;/p&gt;

&lt;p&gt;Fast forward to &lt;a href="https://zed.dev"&gt;Zed&lt;/a&gt; going open source, and I grew interested. A new editor by the folks who originally made Atom sounded cool, but also, so did something new. I had been using VS Code since I started as a dev, and other than changing my color scheme here and there, I hadn't really tried to branch out. When I launched Zed for the first time, I noticed the welcome screen had a checkbox for enabling Vim mode. That's cool, I thought, Vim mode out of the box? Sure, I'll give it a shot. So I took this as an opportunity to not only try out a new editor, but also learn Vim motions.&lt;/p&gt;

&lt;p&gt;This actually went surprisingly well. I also watched a course on &lt;a href="https://zerotomastery.io"&gt;Zero to Mastery&lt;/a&gt; that went into more depth on not only the motions, but also taught me advanced motions and how things like registers and marks worked. Unfortunately, I was frequently running into problems in Zed where certain things (marks, for example) weren't supported in Zed. The course was being taught using the &lt;a href="https://github.com/VSCodeVim/Vim"&gt;Vim plugin&lt;/a&gt; for VS Code, so I decided to move back over to VSC while continuing through the course.&lt;/p&gt;

&lt;p&gt;This was where I had my first internal struggle. At some point I thought, this is kind of silly. Why am I using a plugin to emulate Vim when the whole point was to get away from VSC. I had also found ways to get around some of my issues in Zed, but why do that when I was still just using a crippled version of Vim? So I decided to switch over to Neovim.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I'm not in the slightest implying that there is anything &lt;em&gt;wrong&lt;/em&gt; with VSC or Zed. I still think VSC is great, and I'm still very closely following Zed as I'm still &lt;strong&gt;very&lt;/strong&gt; interested in it's direction. I was just having so much fun, and as &lt;a href="https://x.com/_Ronini/status/1772286640687398965"&gt;I've said before&lt;/a&gt;, following your curiosity is so important for growth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  LazyVim
&lt;/h3&gt;

&lt;p&gt;At the end of the above mentioned course, there was a section on Neovim, and in that section the instructor walks through the process of installing &lt;a href="https://www.lazyvim.org/"&gt;LazyVim&lt;/a&gt;. This seemed great! A fully-functioning IDE in Neovim, right out of the box? Fantastic.&lt;/p&gt;

&lt;p&gt;In my case, this couldn't have been further from the truth. In fact, this was the first time I almost gave up on vim all together. LazyVim is actually great. It has so many useful plugins, lots of great defaults, and it saves you lots of time on configuring Neovim. For me though, it was so incredibly &lt;em&gt;overwhelming&lt;/em&gt;. There was just so much, and if I wanted to change something, I was totally lost on where to go to change it. I think LazyVim actually does a good job of documenting things, but as my first experience with Neovim, a lot of it just simply didn't make sense to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kickstart
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IDftmmLX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExN2drOGh0MjdidDh3d2k0YTM3MXFmeWk2YmlodG1nZ3N0b2F6ZTg2ayZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/5hmmIVqBr9GJXxiikr/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDftmmLX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExN2drOGh0MjdidDh3d2k0YTM3MXFmeWk2YmlodG1nZ3N0b2F6ZTg2ayZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/5hmmIVqBr9GJXxiikr/giphy.gif" alt="A man kickstarting a motorcycle." width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I backed out and moved back to going back and forth between Zed and VSC for a week or so. Then I remembered I had seen &lt;a href="https://www.youtube.com/watch?v=m8C0Cq9Uv9o"&gt;a video by TJ&lt;/a&gt; on &lt;a href="https://github.com/nvim-lua/kickstart.nvim"&gt;Kickstart&lt;/a&gt;, a more minimal &lt;strong&gt;launch point&lt;/strong&gt; for your Neovim config. This resonated more with me and how I learn.&lt;/p&gt;

&lt;p&gt;You see, I like taking things a little slower. I do enjoy jumping in, getting my hands dirty, and learning by doing, rather than by watching/reading. However, I do think there is a line to how uncomfortable I can be before it just becomes too much. Kickstart was the perfect balance and was exactly what I was looking for. It provides some sensible defaults for various options and keymaps, some basic plugins, and the best part? It's all in a single, well-documented file. Combine this with the video linked above, and I quickly felt like I could get up to speed. Within a day or two, I had an editor that I felt comfortable enough with to actually use all day for work.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Second Time I Almost Gave Up
&lt;/h3&gt;

&lt;p&gt;Things seemed to be going pretty well for a day or two, but I didn't quite have my Vue tooling set up properly. I spend most of my day working in Vue, and without getting this set up properly, I knew it was only going to be a matter of time before I was back in VSC with all the tooling that I had come to appreciate.&lt;/p&gt;

&lt;p&gt;So I started trying to get it set up. I started with some googling, which lead to reading various forms of documentation. Here is where the problems started. Vue's official docs point to a repo that shows how to install the recommended tooling via something I had never heard of called &lt;code&gt;coc-nvim&lt;/code&gt;. After talking with Dreams of Code, it sounded like that was something I should avoid as it was an older way of dealing with LSPs.&lt;/p&gt;

&lt;p&gt;Wait, LSPs. I've heard that before.. right?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, I had. In TJ's video I linked above and also in the documentation in the init.lua file for Kickstart. Both were just so information dense, that I forgot a lot of the information that wasn't immediately relevant.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I kept looking and eventually found the documentation for how to set up Volar in combination with TS Server. I got this set up and it seemed to be working! I was seeing the same functionality (for the most part. The core functionality I felt was necessary at least.) that I had in VSC, and I thought everything was good to go. Well. Not Quite.&lt;/p&gt;

&lt;p&gt;I guess while setting this all up, browsing various files and doing basic testing, I had neglected to save any of the files I was doing my testing in. The next day, when I performed my first code change, I hit save and... everything disappeared. My entire file. All the code was replaced with blank lines, and my only option was to &lt;code&gt;q!&lt;/code&gt; out of Neovim, and perform a &lt;code&gt;git checkout&lt;/code&gt; on the file I had edited to recover the code. This issue was particularly annoying because I tried to just simply undo everything by hitting &lt;code&gt;u&lt;/code&gt;, but then every time I saved, it would happen again. Meaning there was no way for me to save the file without losing everything and being forced to reset the file with Git.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The more experienced Vim users will know what's going on here, and will have by no doubt figured out that I &lt;em&gt;could&lt;/em&gt; actually save without this issue. We're getting there. Settle down.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some frustration, mild panic, and a few minutes (hours) of frantic googling later - I found my problem on a GitHub issue. I had assumed that this was related to my config, as commenting out my Volar and TS Server setup in my &lt;code&gt;init.lua&lt;/code&gt; prevented this from happening. Unfortunately, I just didn't really understand &lt;em&gt;why&lt;/em&gt;. Turns out, it was a bug related to TS Server and the &lt;code&gt;format on save&lt;/code&gt; action.&lt;/p&gt;

&lt;p&gt;I fixed my issue, and was able to finish my workday without more hiccups, but at this point I was beginning to question everything. Why was I bothering to learn Vim. I had learned the motions, but I was also &lt;em&gt;very&lt;/em&gt; competent with VS Code's keybindings and was still very fast ... just not as efficient. Did it matter? Did I ever even stop to ask myself &lt;em&gt;why&lt;/em&gt; I was doing this? Did I really want to move to a tool that was going to end up requiring this level of frustration?&lt;/p&gt;

&lt;h3&gt;
  
  
  Difficulty Is Fun
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ARSvUsWD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExYm5lOG10d3loMzV5eDh5a2ppNDd5dGtmMGlqamtsMDgwcTZzeTI4aiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l49JKCSoloVTGjmWQ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ARSvUsWD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExYm5lOG10d3loMzV5eDh5a2ppNDd5dGtmMGlqamtsMDgwcTZzeTI4aiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l49JKCSoloVTGjmWQ/giphy.gif" alt="A knight warming his hands by the famous infamous bon fire made famous by the video game series Dark Souls" width="450" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is it. This was the thing that Neovim &lt;em&gt;really&lt;/em&gt; taught me about myself. Yeah, it taught me that learning you tools is important. It taught me that stopping to question whether or not you really need all those extensions or whether all those different buttons, icons, and notifications in my editor were even important.&lt;/p&gt;

&lt;p&gt;More than anything, it made me reflect. When I almost gave up because things were hard, I spent a couple days not only feeling bummed out, but also thinking about what went wrong. I mean, this shouldn't be that surprising right? It's a large portion of why so many of us like to code. We like solving problems. So I came back. Why? Because I &lt;em&gt;like&lt;/em&gt; to do difficult things.&lt;/p&gt;

&lt;p&gt;I get the most enjoyment out of competitive or difficult video games like League of Legends and Dark souls. I get more enjoyment out of doing things "the hard way" frequently, just because it's more engaging. No, I don't always. I'm not out here mowing my lawn with scissors, but I do find more difficult activities to be more engaging and ✨rewarding✨.&lt;/p&gt;

&lt;p&gt;So, at least for now, I'm going to continue using Neovim. I haven't run into any other issues since that day, either. Maybe something like that will happen again, but I really think that the "I lost x amount of time on my Neovim config" comments are largely self-induced. I really think that, just like all software, you may encounter bugs, but you don't &lt;em&gt;have&lt;/em&gt; to "lose" a bunch of time fiddling with your config &lt;strong&gt;if you don't want to&lt;/strong&gt;. I've spent another handful of hours, but it's largely been because I've added a few more plugins here and there, messed with my keymaps, or I've just simply spent some time going over everything to make sure I &lt;strong&gt;really&lt;/strong&gt; understand &lt;strong&gt;my&lt;/strong&gt; config.&lt;/p&gt;

&lt;p&gt;At the end of the day, that's what it really is. Yours. &lt;strong&gt;That's&lt;/strong&gt; what makes Neovim special.&lt;/p&gt;

&lt;p&gt;Until next time. Cya nerds. 👋&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Build A Dark Theme Toggle With The Composition API</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Mon, 17 Aug 2020 16:52:14 +0000</pubDate>
      <link>https://forem.com/_ronini/build-a-dark-theme-toggle-with-the-composition-api-nfc</link>
      <guid>https://forem.com/_ronini/build-a-dark-theme-toggle-with-the-composition-api-nfc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post first appeared on my &lt;a href="https://ronini.dev/build-a-dark-theme-toggle-with-the-composition-api/"&gt;personal blog&lt;/a&gt;. Make sure you check it out to view this functionality live, and stay for the extra content (:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I recently built a theme toggle for my personal site because, well, everything has a dark theme these days right?&lt;br&gt;
I've spent a lot of time with the composition api recently and after starting to impliment this with the options api,&lt;br&gt;
it became pretty obvious how much code readability would improve by using the composition api and abstracting the functionality&lt;br&gt;
to a separte file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Important note here: I am using the &lt;a href="https://github.com/vuejs/composition-api"&gt;vue-compositon-api-plugin&lt;/a&gt; because I am adding this functionality to my gridsome site which is still using Vue 2.x.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Composables
&lt;/h3&gt;

&lt;p&gt;I'm going to start by creating a &lt;code&gt;composables&lt;/code&gt; folder in my &lt;code&gt;src&lt;/code&gt; directory. This is totally optional, but I assume this is going&lt;br&gt;
to become the best-practice when it comes to drectory structore and code organization. I'm naming the folder &lt;code&gt;composables&lt;/code&gt; because&lt;br&gt;
these function abstractions are called &lt;a href="https://composition-api.vuejs.org/#code-organization"&gt;composition functions&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  useTheme.js
&lt;/h3&gt;

&lt;p&gt;Now inside the &lt;code&gt;composables&lt;/code&gt; directory, I'm going to create a new file, &lt;code&gt;useTheme.js&lt;/code&gt;. &lt;code&gt;useX&lt;/code&gt; is also a future best practice, and&lt;br&gt;
is the &lt;a href="https://composition-api.vuejs.org/#code-organization"&gt;encouraged way to name&lt;/a&gt; your composition functions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is a recommended convention to start the function's name with &lt;code&gt;use&lt;/code&gt; to indicate that it is a composition function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inside &lt;code&gt;useTheme&lt;/code&gt; I'm going to add some boiler plate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&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;@vue/composition-api&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="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTheme&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;currentTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// @TODO&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;toggleTheme&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;Key things to note here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I'm importing &lt;code&gt;ref&lt;/code&gt; from &lt;code&gt;@vue/composition-api&lt;/code&gt;. In a normal Vue 3 application this would just be &lt;code&gt;vue&lt;/code&gt;, but I'm using the composition api in a Vue 2 app with a plugin.&lt;/li&gt;
&lt;li&gt;  I'm initializing a ref called &lt;code&gt;currentTheme&lt;/code&gt;, which is being initialized with a default value of &lt;code&gt;light&lt;/code&gt;. This will be the default theme when a user visits.&lt;/li&gt;
&lt;li&gt;  I'm returning &lt;code&gt;currentThem&lt;/code&gt; and the function &lt;code&gt;toggleTheme&lt;/code&gt; from the &lt;code&gt;use&lt;/code&gt; function. This is important to how this all works and I'll explain in more detail later.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Toggling a theme
&lt;/h3&gt;

&lt;p&gt;Now I'll impliment the toggle theme function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&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;@vue/composition-api&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="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTheme&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;currentTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleTheme&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;currentTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&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="nf"&gt;setLightTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setDarkTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;toggleTheme&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;...That's it!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;wtf?! 😒 - you, probably&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dad jokes aside, lets impliment those two theme functions!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setLightTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;currentTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--primary&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;var(--purple)&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--background&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;var(--bg--light)&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var(--text--light&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--link-text&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;var(--link-text--light&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--active-link-text&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;var(--active-link-text--light&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--shadow&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;var(--shadow--light&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--quote-bg&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;var(--quote-bg--light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClient&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&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;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setDarkTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;currentTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--primary&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;var(--teal)&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--background&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;var(--bg--dark)&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var(--text--dark&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--link-text&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;var(--link-text--dark&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--active-link-text&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;var(--active-link-text--dark&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--shadow&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;var(--shadow--dark&lt;/span&gt;&lt;span class="dl"&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;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--quote-bg&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;var(--quote-bg--dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClient&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&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;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The accompanying styles:&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="c"&gt;/* variables */&lt;/span&gt;
&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--purple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#6200ee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--purple-dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#400088&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--teal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#04dac6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="py"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--purple&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--primary-light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;265&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;95%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--primary-dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#5d3991&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#04dac6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fafafa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--off-white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--black&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1a1a1a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--darker-grey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--dark-grey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4e4c4c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--grey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#718096&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--gray-light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#718096&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c"&gt;/* Dark Theme */&lt;/span&gt;
    &lt;span class="py"&gt;--bg--dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000c1d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--text--dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--off-white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--link-text--dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--off-white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--active-link-text--dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--secondary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--shadow--dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#121212&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--project-border--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--quote-bg--dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;81&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;/* Light Theme */&lt;/span&gt;
    &lt;span class="py"&gt;--bg--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--text--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--darker-grey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--link-text--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--dark-grey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--active-link-text--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--shadow--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--grey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--project-border--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--quote-bg--light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--primary-light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--bg--light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--text--light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--link-text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--link-text--light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--active-link-text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--primary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--shadow--light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--project-border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--project-border--light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="py"&gt;--quote-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--quote-bg--light&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;So in these functions I'm:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting the value of the currentTheme, because I need to keep track of what the active theme is.&lt;/li&gt;
&lt;li&gt;Using the native browser &lt;code&gt;document.documentElement.style.setProperty&lt;/code&gt; function, I'm finding the CSS variable that I need to change, and then passing in what I want the new valule to be.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;If this is your first time seeing &lt;code&gt;document.documentElement.style.setProperty()&lt;/code&gt; I &lt;strong&gt;highly&lt;/strong&gt; recommend checking out &lt;a href="https://davidwalsh.name/css-variables-javascript"&gt;David Walsh's article&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last line here is very specific to my development environment. Since I'm using Gridsome, when my site is built on Netlify it's going to run through all Vue components and turn them into static HTML. &lt;code&gt;localStorage&lt;/code&gt; does not exist in Node, so trying to access it here will cause the build to fail. I'm using &lt;code&gt;process.isClient&lt;/code&gt; to check if the current environment is in the browser. If it is, then it executes this line, setting the current theme in local storage. If not, the line is just skipped.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;x &amp;amp;&amp;amp; y()&lt;/code&gt; is just shorthand for &lt;code&gt;if(x) { y() }&lt;/code&gt;. If the first value is true, the latter is executed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Adding the composable to a Vue component
&lt;/h3&gt;

&lt;p&gt;Now to actually &lt;em&gt;use&lt;/em&gt; this new functionality, it needs to be imported to a Vue component!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm only going to show the relevant pieces here, but my personal site is open source and I definitely encourage you to check out the &lt;a href="https://github.com/Roninii/portfolio/blob/master/src/composables/useTheme.js"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/Roninii/portfolio/blob/master/src/layouts/Nav.vue"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the template, I'll add a button with a click handler that points to the &lt;code&gt;toggleTheme&lt;/code&gt; function.&lt;br&gt;
This is just a regular 'ol button element with a &lt;a href="https://fontawesome.com/icons/lightbulb?style=regular"&gt;font awesome lightbulb icon inside&lt;/a&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;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"toggleTheme"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"theme-toggle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"far fa-lightbulb"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the script tag, I'll import the composable, extract the &lt;code&gt;toggleTheme&lt;/code&gt; function, and return it from the &lt;code&gt;setup&lt;/code&gt; function so it can be referenced in the template.&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;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useTheme&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;~/composables/useTheme&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="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setup&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="nx"&gt;toggleTheme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;toggleTheme&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how I'm destructuring &lt;code&gt;toggleTheme&lt;/code&gt; from the &lt;strong&gt;return&lt;/strong&gt; value of &lt;code&gt;useTheme&lt;/code&gt;? This is what I mentioned earlier. Some of you that have been working with javascript&lt;br&gt;
for a long time might have already recognized what's going on here. &lt;code&gt;toggleTheme&lt;/code&gt; is using a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;closure&lt;/a&gt; to keep the&lt;br&gt;
reference to &lt;code&gt;currentTheme&lt;/code&gt; in sync!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Closures are a huge and complicated concept that is out of the scope of this article. They're 100% worth learning though, and &lt;a href="https://ui.dev/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/"&gt;this&lt;/a&gt; is a great article to start with!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now when the user clicks on the lightbulb:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;toggleTheme&lt;/code&gt; function will be called,&lt;/li&gt;
&lt;li&gt;The value of &lt;code&gt;currentTheme&lt;/code&gt; will be checked, and the appropriate theme function will be called.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works!&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcgsyzq8t9ow6dfig4rmw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcgsyzq8t9ow6dfig4rmw.gif" alt="ronini.dev toggling between dark and light mode." width="640" height="303"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Saving the user's preference
&lt;/h3&gt;

&lt;p&gt;Some of you might've noticed that in the &lt;code&gt;set[X]Theme&lt;/code&gt; functions, the current theme is being saved to local storage. This is so that the user's preference for dark or light&lt;br&gt;
theme can be saved. However, as the code stands, nothing is actually &lt;em&gt;done&lt;/em&gt; with this data, and in fact, it causes a bug. So to take care of that,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTheme&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;currentTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// check local storage for saved theme preference and set it&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;themePreference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;theme&lt;/span&gt;&lt;span class="dl"&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;themePreference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;currentTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;themePreference&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;currentTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;setLightTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;setDarkTheme&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;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;process.isClient&lt;/code&gt; is being checked again so that this doesn't fail during build, as mentioned earlier.&lt;br&gt;
If the code is being executed in the browser, the &lt;code&gt;themePreference&lt;/code&gt; is retrieved from the user's &lt;code&gt;localStorage&lt;/code&gt;. If the value&lt;br&gt;
of &lt;code&gt;themePreference&lt;/code&gt; is truthy, then the value of &lt;code&gt;currentTheme&lt;/code&gt; is set to the retrieved value, and then the appropriate &lt;code&gt;set[X]Theme&lt;/code&gt;&lt;br&gt;
function is executed so that the the user's preference is now set on load!&lt;/p&gt;

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

&lt;p&gt;I had a blast implimenting this, and being able to pull all this logic out into a separate file and use the power of JavaScript's modularity is&lt;br&gt;
an awesome feeling. Did you anything? Did you notice an implimentation detail that could be improved? Be sure to let me know on twitter!&lt;/p&gt;

&lt;p&gt;As always, until next time 🖖🏻&lt;/p&gt;

</description>
      <category>vue</category>
      <category>100daysofcode</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Let's Build A Game With Vue 3</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Mon, 10 Aug 2020 13:39:31 +0000</pubDate>
      <link>https://forem.com/_ronini/let-s-build-a-game-with-vue-3-4j7n</link>
      <guid>https://forem.com/_ronini/let-s-build-a-game-with-vue-3-4j7n</guid>
      <description>&lt;p&gt;&lt;strong&gt;This post first appeared on my &lt;a href="https://ronini.dev/blog/let-s-build-a-game-with-vue-3/"&gt;blog&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today we're going to be building a tic-tac-toe clone like the one seen in the &lt;a href="https://reactjs.org/tutorial/tutorial.html#before-we-start-the-tutorial"&gt;React docs&lt;/a&gt;. Except we're going to be using the Vue 3 Composition API.&lt;/p&gt;

&lt;p&gt;🗣️You can check out the source code &lt;a href="https://github.com/roninii/vue3-tic-tac-toe"&gt;here&lt;/a&gt; or the live demo &lt;a href="https://tic-tac-vue.netlify.com"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're totally new to the Vue 3 composition API, I recommend you check out my post on &lt;a href="https://ronini.dev/blog/composition-api-what-is-it-and-why/"&gt;that first&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This post will assume you have some basic understanding of the API, as well as Vue and JavaScript.&lt;/p&gt;

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




&lt;p&gt;I'm going to be using &lt;a href="https://github.com/vitejs/vite"&gt;Vite&lt;/a&gt; for quick setup as well as a lightening fast dev server. I definitely recommend checking it out! It uses Vue 3 by default, so we don't have any additional set up to worry about to get going.&lt;/p&gt;

&lt;p&gt;To create the project run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init vite-app tic-tac-toe
&lt;span class="nb"&gt;cd &lt;/span&gt;tic-tac-toe
npm i
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be all set up and if you open your browser to &lt;code&gt;localhost:3000&lt;/code&gt; you should be looking at something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dyWUBsQd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ronini.dev/img/vite-starter.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dyWUBsQd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ronini.dev/img/vite-starter.png" alt="Project scaffolding with Vite" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a moment to look around the code if you want, otherwise lets get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Board
&lt;/h2&gt;




&lt;p&gt;First lets start creating the board. We will start by renaming the &lt;code&gt;HelloWorld.vue&lt;/code&gt; component to &lt;code&gt;Board.vue&lt;/code&gt;(Don't forget to change the imports!), then we will alter the template in &lt;code&gt;App.vue&lt;/code&gt; along with replacing the boiler plate in the now named &lt;code&gt;Board.vue&lt;/code&gt;.&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="c1"&gt;// App.vue&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Board&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;./components/Board.vue&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="k"&gt;default&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Board&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;The board and related styles:&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="c1"&gt;// Board.vue&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'board'&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;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'vertical-line-1'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&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;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'vertical-line-2'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&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="nc"&gt;Square&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&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;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
import Square from './Square.vue'

export default &lt;span class="si"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Board&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Square&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;script&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;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
.board &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.board::before, .board::after &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linear&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="nx"&gt;b883&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;35495&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.vertical-line-1, .vertical-line-2 &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linear&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="nx"&gt;b883&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;35495&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.board::before, .board::after &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&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="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.board::before &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.board::after &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.vertical-line-1, .vertical-line-2 &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&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="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="nx"&gt;deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.vertical-line-1 &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.vertical-line-2 &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="o"&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;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are just taking care of the basic markup and styling. Using a couple spans, and the board's &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; elements to take care of the lines that make up the game board. We're also registering a &lt;code&gt;Square&lt;/code&gt; component, which will be responsible for rendering the actual buttons that the user clicks to place their &lt;code&gt;X&lt;/code&gt; or &lt;code&gt;O&lt;/code&gt; , respectively. Let's build that now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Squares
&lt;/h2&gt;




&lt;p&gt;So before jumping into the code, let's think about what we expect from our Square component:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It should receive a value - When the user clicks on the button, it should receive the value of the current player, and we'll display that value in our template.&lt;/li&gt;
&lt;li&gt;It should probably disable the button after it's been passed a value and/or if there is a winner.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's ... really it! So let's build it out:&lt;/p&gt;

&lt;p&gt;First let's take care of the template and the styles. We'll add a button with a disabled attribute which we will bind to &lt;code&gt;winner || value&lt;/code&gt;, so that we can dynamically mark this button as disabled based on whether it has been clicked, or if the game is over. For accessibility reasons, we'll add a &lt;code&gt;name&lt;/code&gt; attribute that we'll bind to a prop called &lt;code&gt;label&lt;/code&gt;.&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="c1"&gt;// Square.vue&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&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;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'square'&lt;/span&gt;
        &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"label"&lt;/span&gt;
        &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'winner || value'&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;value&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;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;template&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;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
.square &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.square:hover &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.square:focus &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="nx"&gt;b88330&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.square:first-child,
.square:nth-child(2),
.square:nth-child(3) &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.square:nth-child(3),
.square:nth-child(6),
.square:last-child &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.square:nth-child(7),
.square:nth-child(8),
.square:last-child &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

.square:first-child,
.square:nth-child(4),
.square:nth-child(7) &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&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;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's add the JS! Since our component isn't in charge of maintaining any state, it'll be pretty lean. All we need is to declare our props, &lt;code&gt;label&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, and &lt;code&gt;winner&lt;/code&gt;.&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;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
export default &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;winner&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="si"&gt;}&lt;/span&gt;,
});
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Cool! However, if you've been following along, you'll likely notice our app doesn't actually &lt;em&gt;do&lt;/em&gt; anything yet. Let's add the game logic now!&lt;/p&gt;

&lt;h2&gt;
  
  
  Game Logic
&lt;/h2&gt;

&lt;p&gt;Since we're using the &lt;a href="https://composition-api.vuejs.org/"&gt;composition API&lt;/a&gt;, we can o organize our code in related blocks, and then initiate all of that in the &lt;code&gt;setup&lt;/code&gt; function. That might sound complicated, so lets take a look at the code and see what that means.&lt;/p&gt;

&lt;p&gt;Let's plan everything out before we start writing code. (I'm just doing this to look good. I almost always code before thinking, which you're not supposed to do 🤫)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We're going to keep track of the board, which we'll represent with an array. Each entry in the array will be one of the boxes on the board.&lt;/li&gt;
&lt;li&gt;The board will also need to keep track of who's turn it is, and what value (&lt;code&gt;x&lt;/code&gt; or &lt;code&gt;o&lt;/code&gt;) that player represents.&lt;/li&gt;
&lt;li&gt;When a square on the board is clicked, we should alter it's value in our array and notify the square of the change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cool! Now that we know how everything &lt;em&gt;should&lt;/em&gt; work, lets get to coding.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nf"&gt;setup&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;board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playerValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X&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;markSquare&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&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;boardCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;boardCopy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;boardCopy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;playerValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;playerValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;O&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="nx"&gt;playerValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X&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="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;playerValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;markSquare&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;Inside our setup function we're initializing two variables, &lt;code&gt;board&lt;/code&gt; and &lt;code&gt;playerValue&lt;/code&gt;. We're using &lt;code&gt;ref&lt;/code&gt; here, a new addition from the composition api, to wrap the variable in a reactive reference. &lt;strong&gt;&lt;em&gt;Reactive Reference&lt;/em&gt;&lt;/strong&gt; is an important distinction here, because you have to remember this is an object, and you have to add &lt;code&gt;.value&lt;/code&gt; to actually access the value held within. This allows us to use Vue's reactivity system, so that anywhere these variables are referenced will be updated when it changes.&lt;/p&gt;

&lt;p&gt;Next we declare a function called &lt;code&gt;markSquare&lt;/code&gt;, that takes one parameter, &lt;code&gt;i&lt;/code&gt;. This is common shorthand for &lt;code&gt;index&lt;/code&gt;, and you'll see why we're expecting this value shortly. The function then creates a copy of the board, assigning it to the variable &lt;code&gt;boardCopy&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 I'm using &lt;code&gt;const&lt;/code&gt; here out of personal preference. I prefer to always use const unless I &lt;em&gt;need&lt;/em&gt; to change the value, in which case I will change it to &lt;code&gt;let&lt;/code&gt;. Since &lt;code&gt;ref&lt;/code&gt; actually returns a reactive &lt;em&gt;object&lt;/em&gt; we can access and change &lt;code&gt;.value&lt;/code&gt; without throwing errors. For more info on how that works, I recommend checking &lt;a href="https://ui.dev/var-let-const/"&gt;this article over at ui.dev&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We'll now access the value located in our &lt;code&gt;boardCopy&lt;/code&gt; array, located at the index that was passed to our function, and change the value from &lt;code&gt;null&lt;/code&gt; (the initial value) to the value of whoever's turn it is. After that has been taken care of, we will just replace our current board with the copy. Before we return from our function, we're going to check to see who's turn it is and set the appropriate value so that the next player can begin their turn.&lt;/p&gt;

&lt;p&gt;Last step here is the explicit return object from our &lt;code&gt;setup&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;playerValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;markSquare&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;Anything returned from the setup function becomes available in the template.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's Important to note that passing a &lt;code&gt;ref&lt;/code&gt; to the return object gets automagically unpacked by Vue. So you'll be able to reference it in the template at &lt;code&gt;board&lt;/code&gt; instead of &lt;code&gt;board.value&lt;/code&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Updating our board template
&lt;/h2&gt;

&lt;p&gt;Now that we have our game logic in place, let's add the updates to the board so that we can start applying this logic and interacting with the game!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ &amp;lt;h1 v-else&amp;gt;Next Up: {{ playerValue }}&amp;lt;/h1&amp;gt;
&lt;/span&gt; &amp;lt;div class='board'&amp;gt;
 &amp;lt;span class='vertical-line-1'&amp;gt;&amp;lt;/span&amp;gt;
 &amp;lt;span class='vertical-line-2'&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;Square
&lt;span class="gi"&gt;+    v-for='(square, i) in board'
+    :key='`square-${i}`'
+    :label="`square-${i}`"
+    :value='square'
+    @click='markSquare(i)'
&lt;/span&gt;  /&amp;gt;
 &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright! So we've added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  An &lt;code&gt;h1&lt;/code&gt; to show us who's turn it is.&lt;/li&gt;
&lt;li&gt;  A loop via &lt;code&gt;v-for&lt;/code&gt; to create a &lt;code&gt;Square&lt;/code&gt; component for &lt;em&gt;each&lt;/em&gt; value in our &lt;code&gt;Board&lt;/code&gt; array.&lt;/li&gt;
&lt;li&gt;  A &lt;code&gt;:key&lt;/code&gt; attribute so that Vue can keep track of each instance of &lt;code&gt;Square&lt;/code&gt;. This helps Vue keep track of what should and should not be updated.&lt;/li&gt;
&lt;li&gt;  We're now passing in the current index to the label prop. So our button label should read something like &lt;code&gt;square-1&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;:value&lt;/code&gt; of this square. We're getting this from our loop. Every square should have a value of &lt;code&gt;null&lt;/code&gt; on initial render, and as the user clicks it will be updated with the current player's value.&lt;/li&gt;
&lt;li&gt;  An &lt;code&gt;on click&lt;/code&gt; handler that calls our &lt;code&gt;markSquare&lt;/code&gt; function, passing in the &lt;code&gt;index&lt;/code&gt; of &lt;strong&gt;&lt;em&gt;this&lt;/em&gt;&lt;/strong&gt; square so that we update the correct value in our board array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if you load up the game, you should be able to click through each tile, marking each with an &lt;code&gt;x&lt;/code&gt; or an &lt;code&gt;o&lt;/code&gt;! We're still missing a couple features though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We have no way of determining who won&lt;/li&gt;
&lt;li&gt;Nothing happens when the game ends, the user would probably like to have some sort of text in the UI that tells them &lt;em&gt;who&lt;/em&gt; won, and that the game is over.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Calculating a winner and notifying the user.
&lt;/h2&gt;

&lt;p&gt;First, we'll jump back down to our &lt;code&gt;setup&lt;/code&gt; function to add the logic for calculating a winner. I borrowed the majority of the below function straight from the &lt;a href="https://reactjs.org/tutorial/tutorial.html#declaring-a-winner"&gt;React Docs&lt;/a&gt;, with some modifications to Vue-ify it.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculateWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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;lines&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="mi"&gt;0&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="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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; Wins`&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;board&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;val&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="s1"&gt;Tie!&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="kc"&gt;null&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;So a few things are happening here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We're creating an array of arrays, &lt;code&gt;lines&lt;/code&gt;, that houses all the possible winning combinations.&lt;/li&gt;
&lt;li&gt;We loop through each of the combos, checking to see if the current state of our board matches any of the possible conditions and declaring a winner if it does.&lt;/li&gt;
&lt;li&gt;If there is no winner, and the board is full, declare the game a tie.&lt;/li&gt;
&lt;li&gt;If the board isn't full and it isn't full yet, just return null.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's remember to declare this in our &lt;code&gt;return&lt;/code&gt; object so we can use this computed function in the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;return {
&lt;/span&gt;    board,
    playerValue,
    markSquare,
&lt;span class="gi"&gt;+ calculateWinner
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can reference this in our template to both disable all remaining squares on the board, and show a message to the user if a winner has been declared or if there is a tie.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ &amp;lt;header v-if='calculateWinner' class='header'&amp;gt;
+    &amp;lt;h1&amp;gt;
+        {{ calculateWinner }}
+    &amp;lt;/h1&amp;gt;
+ &amp;lt;/header&amp;gt;
&lt;/span&gt; &amp;lt;h1 v-else&amp;gt;Next Up: {{ playerValue }}&amp;lt;/h1&amp;gt;
 &amp;lt;span ref='boardRef' class='confetti-origin'&amp;gt;&amp;lt;/span&amp;gt;
 &amp;lt;div class='board'&amp;gt;
 &amp;lt;span class='vertical-line-1'&amp;gt;&amp;lt;/span&amp;gt;
 &amp;lt;span class='vertical-line-2'&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;Square
    v-for='(square, i) in board'
    :key='`square-${i}`'
    :label="`square-${i}`"
    :value='square'
    @click='markSquare(i)'
&lt;span class="gi"&gt;+    :winner='calculateWinner'
&lt;/span&gt;  /&amp;gt;
 &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! The game is complete! We can add a little polish though. How about a reset button so the user can play again, and we can add some confetti to celebrate the winner!&lt;/p&gt;

&lt;h2&gt;
  
  
  Reset and Celebrate
&lt;/h2&gt;

&lt;p&gt;First let's add the reset button, as well as a the accompanying logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; &amp;lt;header v-if='calculateWinner' class='header'&amp;gt;
     &amp;lt;h1&amp;gt;
         {{ calculateWinner }}
     &amp;lt;/h1&amp;gt;
&lt;span class="gi"&gt;+    &amp;lt;button class='reset' @click='reset'&amp;gt;Play Again&amp;lt;/button&amp;gt;
&lt;/span&gt; &amp;lt;/header&amp;gt;
 &amp;lt;h1 v-else&amp;gt;Next Up: {{ playerValue }}&amp;lt;/h1&amp;gt;
 &amp;lt;span ref='boardRef' class='confetti-origin'&amp;gt;&amp;lt;/span&amp;gt;
 &amp;lt;div class='board'&amp;gt;
 &amp;lt;span class='vertical-line-1'&amp;gt;&amp;lt;/span&amp;gt;
 &amp;lt;span class='vertical-line-2'&amp;gt;&amp;lt;/span&amp;gt;
   &amp;lt;Square
     v-for='(square, i) in board'
     :key='`square-${i}`'
     :label="`square-${i}`"
     :value='square'
     @click='markSquare(i)'
     :winner='calculateWinner'
   /&amp;gt;
 &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ const reset = () =&amp;gt; {
&lt;/span&gt;        board.value = Array(9).fill(null)
        playerValue.value = 'X'
    }
&lt;span class="err"&gt;
&lt;/span&gt;    return {
        board,
        markSquare,
        playerValue,
&lt;span class="gi"&gt;+       reset
&lt;/span&gt;  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yayyy 🎉 Now our users can play again if they want to.&lt;/p&gt;

&lt;p&gt;As for the confetti, we'll use a small library from npm, &lt;a href="https://www.npmjs.com/package/dom-confetti"&gt;dom-confetti&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install it via &lt;code&gt;npm i dom-confetti&lt;/code&gt;, and then in &lt;code&gt;Board.vue&lt;/code&gt; we can import it like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;confetti&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;../../node_modules/dom-confetti/src/main.js&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;blockquote&gt;
&lt;p&gt;Note: If you're not using Vite, you could just use &lt;code&gt;'dom-confetti'&lt;/code&gt; as the path. I'm using Vite, which requires you to point directly to the file in this case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;confetti&lt;/code&gt; function takes a DOM element as it's parameter, so we'll add an element to our template just for this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; &amp;lt;header v-if='calculateWinner' class='header'&amp;gt;
     &amp;lt;h1&amp;gt;
         {{ calculateWinner }}
     &amp;lt;/h1&amp;gt;
    &amp;lt;button class='reset' @click='reset'&amp;gt;Play Again&amp;lt;/button&amp;gt;
 &amp;lt;/header&amp;gt;
 &amp;lt;h1 v-else&amp;gt;Next Up: {{ playerValue }}&amp;lt;/h1&amp;gt;
&lt;span class="gi"&gt;+ &amp;lt;span ref='boardRef' class='confetti-origin'&amp;gt;&amp;lt;/span&amp;gt;
&lt;/span&gt; &amp;lt;div class='board'&amp;gt;
 &amp;lt;span class='vertical-line-1'&amp;gt;&amp;lt;/span&amp;gt;
 &amp;lt;span class='vertical-line-2'&amp;gt;&amp;lt;/span&amp;gt;
   &amp;lt;Square
     v-for='(square, i) in board'
     :key='`square-${i}`'
     :label="`square-${i}`"
     :value='square'
     @click='markSquare(i)'
     :winner='calculateWinner'
   /&amp;gt;
 &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in the &lt;code&gt;setup&lt;/code&gt; function, we'll declare a &lt;code&gt;ref&lt;/code&gt; that points at this DOM node, and then in the &lt;code&gt;calculateWinner&lt;/code&gt; computed property, we'll call &lt;code&gt;confett&lt;/code&gt; if there is a winner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;setup() {
&lt;/span&gt;&lt;span class="gi"&gt;+   const boardRef = ref(null)
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;    // ...
&lt;span class="err"&gt;
&lt;/span&gt;    const calculateWinner = computed(() =&amp;gt; {
        const lines = [
            [0, 1, 2],
            [3, 4, 5],
            [6, 7, 8],
            [0, 3, 6],
            [1, 4, 7],
            [2, 5, 8],
            [0, 4, 8],
            [2, 4, 6],
        ]
&lt;span class="err"&gt;
&lt;/span&gt;        for (let i = 0; i &amp;lt; lines.length; i++) {
            const [a, b, c] = lines[i]
            if (
                board.value[a] &amp;amp;&amp;amp;
                board.value[a] === board.value[b] &amp;amp;&amp;amp;
                board.value[a] === board.value[c]
            ) {
&lt;span class="gi"&gt;+               confetti(boardRef)
&lt;/span&gt;                return `${board.value[a]} Wins`
            }
        }
&lt;span class="err"&gt;
&lt;/span&gt;        if(board.value.every(val =&amp;gt; val)) return 'Tie!'
&lt;span class="err"&gt;
&lt;/span&gt;        return null
    })
&lt;span class="err"&gt;
&lt;/span&gt;    return {
        board,
&lt;span class="gi"&gt;+       boardRef,
&lt;/span&gt;        markSquare,
        playerValue,
        reset
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Open up your browser and try it out. (or if you haven't been following along, you can check out the live demo &lt;a href="https://tic-tac-vue.netlify.app"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want you can &lt;a href="https://github.com/roninii/vue3-tic-tac-toe"&gt;check out the repo&lt;/a&gt;, where you'll find a couple extras like TS, and refactoring into composition functions! I would've liked to include that here, but that was just out of the scope for this post. If there is enough interest, I'd be happy to make a follow up post!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hope you had fun, and hopefully you learned a thing or two about using the composition api in project setting instead of just theory and small examples!&lt;/p&gt;

&lt;p&gt;Be sure to follow me on all the socials for more content like this! Until next time 🖖🏻&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>Vue Inside AJS?!</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Tue, 04 Aug 2020 13:01:50 +0000</pubDate>
      <link>https://forem.com/_ronini/vue-inside-angularjs-2c4m</link>
      <guid>https://forem.com/_ronini/vue-inside-angularjs-2c4m</guid>
      <description>&lt;p&gt;This post originally appeared on my &lt;a href="https://ronini.dev/blog/vue-inside-ajs"&gt;blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At Winning Streak, we recently began our transition of migrating our biggest project from AngularJS to Vue. This is the why and the how!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vue?
&lt;/h2&gt;




&lt;p&gt;First and foremost - AJS is reaching EOL. It was announced that on &lt;a href="https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c"&gt;July 1st, 2018, AJS would enter into a three year LTS period.&lt;/a&gt; The Angular team has moved onto Angular 2+ (simply named &lt;em&gt;Angular&lt;/em&gt;), and has since stopped development on AJS.&lt;/p&gt;

&lt;p&gt;So... Why &lt;a href="https://vuejs.org"&gt;Vue&lt;/a&gt;? Firstly, &lt;a href="https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c"&gt;it's loved by nearly everyone who has used it&lt;/a&gt;. Secondly, it's arguably one of the easiest frontend frameworks to get up and running with. Lastly, I have lots of experience with it, and so does the &lt;a href="https://twitter.com/CSchliesser"&gt;other developer on my team&lt;/a&gt;! Vue recognizes that AJS got a lot of things right, and builds on those features while eliminating some of the pain points and poor decisions made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;




&lt;p&gt;Since Vue promotes incremental adoption, we chose to take that idea and run with it, but how? I found this &lt;a href="https://codepen.io/al-the-x/pen/MBMLOZ"&gt;amazing pen&lt;/a&gt; - we saw an approach that we knew would work for us.&lt;/p&gt;

&lt;p&gt;The app in question is fairly large, and an integral part of day-to-day operations within the company. This means that a rewrite wouldn't be a great use of time since there are only two of us, and there are still plenty of new features and various fixes/enhancements to work on. We also had to ensure that whatever path we took, it had to live alongside the current implementations without breaking anything.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Okay, cool - but where does the pen come in, and when are you going to get to the point? - you, probably&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So here is the plan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Refactor &lt;em&gt;everything&lt;/em&gt; and get the codebase prepped for a modern approach to old solutions.&lt;/li&gt;
&lt;li&gt;  Replace our build tool, gulp, with Parcel (I'll explain this decision in the next section)&lt;/li&gt;
&lt;li&gt;  Use AJS components as an entry point for Vue components, acting as a wrapper until Vue becomes the larger portion of the app, in which case we could sprint to finally make the swap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Phase 1 - The Refactor
&lt;/h2&gt;




&lt;h3&gt;
  
  
  Step 1: Refactoring components &amp;amp; their templates to model Vue SFC
&lt;/h3&gt;

&lt;p&gt;I have to admit, this part was a little intimidating. There is a &lt;em&gt;lot&lt;/em&gt; of code, and due to the nature of how quickly everything had to be built - there are not a lot of tests - In fact, there aren't &lt;em&gt;any&lt;/em&gt;... So we had to take baby steps, carefully performing reviews along the way.&lt;/p&gt;

&lt;p&gt;First up, refactor the components to more closely model Vue's &lt;a href="https://vuejs.org/v2/guide/single-file-components.html"&gt;SFC approach&lt;/a&gt;. Not only did we love how easy SFCs are to work with and reason about, but refactoring AJS into a close clone of this would make it really easy to transition them into Vue components later on. So we moved all the separate template files into es6 string templates, and packaged them up inside the respective AJS template option.&lt;/p&gt;

&lt;p&gt;From this:&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="c1"&gt;// example.html&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is my component template!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// example.js&lt;/span&gt;
&lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;controller&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="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... component logic ...&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;To this:&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="c1"&gt;// example.js&lt;/span&gt;
&lt;span class="nx"&gt;angular&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&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="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;controller&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="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ... component logic ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nl"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
       &amp;lt;div&amp;gt;
         &amp;lt;h1&amp;gt;This is my component template!&amp;lt;/h1&amp;gt;
       &amp;lt;/div&amp;gt;
    `&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is obviously a trivial example, but it illustrate the point. This refactored component looks &lt;em&gt;very&lt;/em&gt; similar to a Vue SFC, and will take just a few minutes to refactor to Vue syntax down the road.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 : Replace Gulp with Parcel
&lt;/h3&gt;

&lt;p&gt;Let me start by saying,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is absolutely nothing wrong with Gulp.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pitchforks down? Okay, lets move on.&lt;/p&gt;

&lt;p&gt;We chose Parcel for a couple reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  No on &lt;em&gt;really&lt;/em&gt; enjoys working with Webpack.&lt;/li&gt;
&lt;li&gt;  It echos Vue's "easy to get up and running" approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of those points, since it uses Babel under the hood, we also got access to extra javascript features without any extra configuration. A huge benefit, is Parcel's support of Vue SFCs &lt;a href="https://parceljs.org/vue.html"&gt;right out of the box&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since there is no complicated setup or configuration required for Parcel, there isn't much to go over here. All we had to do was eliminate the gulp file that took care of concatenation, bundling, building, etc. Then we created an Index.html file, and an Index.js file that contained the bootstrap logic for the app. Parcel takes care of the rest!&lt;/p&gt;

&lt;p&gt;🔗&lt;a href="https://parceljs.org/getting_started.html"&gt;Check out the official Parcel docs for more info&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Refactor components to default exports
&lt;/h3&gt;

&lt;p&gt;This was the simplest part of the refactor, at was the last step. In ES6, we have support for import/export syntax like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&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;../components/MyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// MyComponent.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... component logic ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we refactor all our angular components to this syntax, we can simplify how register them with Angular, and this will again make the transition to Vue much simpler.&lt;/p&gt;

&lt;p&gt;now in our &lt;code&gt;index.js&lt;/code&gt; file, we can register our components like so:&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="c1"&gt;// first mass import all the components&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;components&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;./components/*.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// loop through all the components and register them&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="k"&gt;default&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;Let's break this down just to clarify what is happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  First we're mass importing everything that ends in &lt;code&gt;.js&lt;/code&gt; in our components directory, and giving this object that contains them all the name of &lt;code&gt;components&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Then we loop through each property in &lt;code&gt;components&lt;/code&gt;, which each of which is a component object.&lt;/li&gt;
&lt;li&gt;  Then we register this component with Angular. &lt;code&gt;Component&lt;/code&gt; is the first argument which is the component's name. &lt;code&gt;components[component].default&lt;/code&gt; is the actual component &lt;em&gt;object&lt;/em&gt;. It's important to note the &lt;code&gt;.default&lt;/code&gt; here, because the object contains a property, default, which is the default export declared in each component file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now instead of registering each component with Angular in each module, they're all being declared and registered in one location in our app. Even more importantly, this won't break when some of them get refactored to Vue components, because the import loop only imports &lt;code&gt;.js&lt;/code&gt; files, not &lt;code&gt;.vue&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 2 - Adding Vue
&lt;/h2&gt;

&lt;p&gt;Now the fun part, and the part I've been dreaming of since I joined the company and started maintaining the AJS code. As previously discussed, this addition of Vue had to be just that - an addition. It needs to work &lt;em&gt;alongside&lt;/em&gt; the existing code, in a &lt;a href="https://africansunroad.com/symbiotic-relationships/#:~:text=Symbiotic%20relationships%201%20Parasitism%20This%20is%20one%20of,by%20a%20second%20species.%20...%20More%20items...%20"&gt;symbiotic&lt;/a&gt; relationship.&lt;/p&gt;

&lt;p&gt;Thankfully, I discovered the codepen mentioned earlier in the article that showcases using AJS to mount our Vue components. This works because Vue, like most SPAs, attaches itself to a part of the DOM, and controls everything within it. This is why most SPA boilerplate just has a single div with an id of "app".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Great. Code please?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Calm down, I'm getting there.&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="c1"&gt;// login.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Login&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;./Login.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;controller&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="nx"&gt;$element&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;vue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;'&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;span class="nl"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;Login ng-non-bindable&amp;gt;&amp;lt;/Login&amp;gt;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;WTF?!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, those were my thoughts exactly.&lt;/p&gt;

&lt;p&gt;So we're importing our Vue component and using Angular to find the custom tag in the DOM, and mount our Vue instance. This works... surprisingly well. Using this method, you can even pass data into the component from Angular! Now our Angular component is actually just a transparent wrapper. It is still &lt;em&gt;registered&lt;/em&gt; with Angular, so we can use any data we need from the Angular layer and still route to this component using our Angular router.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Notice the use of &lt;code&gt;ng-non-bindable&lt;/code&gt; here. Its required so that Angular doesn't try to apply Angular specific bindings to the Vue component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This approach becomes &lt;em&gt;really&lt;/em&gt; cool when you start passing data between the layers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Login&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;./Login.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;controller&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="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$stateParams&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;vue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login&lt;/span&gt;&lt;span class="dl"&gt;'&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="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;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$stateParams&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;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;Login :userId='userId'&amp;gt;&amp;lt;/Login&amp;gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we're using the Angular router to gather the &lt;code&gt;userID&lt;/code&gt;from the \$stateParams (url params), and passing it to the Vue instance. This works the other way too, allowing you to emit an event from the Vue instance that actually calls a method in the Angular instance. You might need to do this for a component that uses an Angular specific third party library, like Angular Bootstrap and modals.&lt;/p&gt;

&lt;p&gt;The best part of this whole set up, is we can author Vue SFCs thanks to the built-in support from Parcel. Then we can import those components and reference them in the Angular instance. Done right, this whole system allows you to slowly replace Angular from the inside out, using Vue to control everything about the app. We will eventually get to a point where Angular is just providing the router and wrapping Vue components, in which case we will just replace it with the Vue router, and remove the Angular components!&lt;/p&gt;

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

&lt;p&gt;So this is how we converted our AJS app to Vue without a total rewrite, and without breaking anything in the process. We planned it for months, but it took only a couple days to sprint on the Parcel conversion, and now all we have to do is author new features in Vue and continue to replace bits and pieces with Vue. Hopefully you learned something, or at least discovered something interesting out of all this! If nothing else, at least it'll be a cool way to document this process 😃. Be sure to follow me on &lt;a href="https://twitter.com/_ronini"&gt;Twitter&lt;/a&gt;, and let me know what you think!&lt;/p&gt;

&lt;p&gt;Until next time! 🖖🏻&lt;/p&gt;

</description>
      <category>vue</category>
      <category>angular</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Composition API - what is it, and why?</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Mon, 13 Jul 2020 14:17:32 +0000</pubDate>
      <link>https://forem.com/_ronini/composition-api-what-is-it-and-why-1nik</link>
      <guid>https://forem.com/_ronini/composition-api-what-is-it-and-why-1nik</guid>
      <description>&lt;h2&gt;
  
  
  Before we even start...
&lt;/h2&gt;

&lt;p&gt;Let's talk about a couple of things that should be noted that the composition API is &lt;strong&gt;purely additive&lt;/strong&gt;. It is &lt;strong&gt;not&lt;/strong&gt; required, nor is the old API &lt;strong&gt;in any way&lt;/strong&gt; being deprecated. This was a huge misunderstanding and a pain point for many Vue developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  So.. Why a new API?
&lt;/h2&gt;

&lt;p&gt;It boils down to a few major pain points that can be encountered when building larger scale Vue apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  TypeScript support is.. not great. Vue does some magic behind the scenes, and therefore type inference just doesn't work the way that one might hope. Now that TypeScript has seemingly taken the JavaScript community under its wing, it has become apparent that better type support is necessary.&lt;/li&gt;
&lt;li&gt;  The organization of component logic. If you've ever worked with a large component file, you might know how hard it can be to figure out... just... wtf is going on. Everything is organized by the options API which works great most of the time, but once a component becomes complex you might find yourself jumping back and forth between the different options just to try and follow along with the logic.&lt;/li&gt;
&lt;li&gt;  Mixins can be confusing. They are the best way to abstract and share certain logic between components as of right now, but they come with a host of their own problems including namespace collisions, and a lack of context about where certain properties are coming from.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Okay so... What is it?
&lt;/h2&gt;

&lt;p&gt;From the RFC summary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A set of additive, function-based APIs that allow flexible composition of component logic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's break that down and see how it relates to our earlier points.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript support
&lt;/h2&gt;

&lt;p&gt;This one is &lt;strong&gt;huge&lt;/strong&gt; for a lot of people. There is no denying that TypeScript is here to stay, and it has plenty of people willing to die on a hill to show how important it is. Regardless of how you feel about it, the IDE support and safety it provides is outstanding for the developer experience.&lt;/p&gt;

&lt;p&gt;Along with the API change the Vue codebase has been rewritten with TypeScript in mind which is something you couldn't say about previous versions. What really makes this easier though, is the removal of the magical &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're unfamiliar with &lt;code&gt;this&lt;/code&gt; in JavaScript or you still struggle with it, I highly recommend &lt;a href="https://ui.dev/this-keyword-call-apply-bind-javascript/"&gt;this article at ui.dev&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Vue, there is a lot of magic happening behind the, and one of those spells that they are casting is the way that &lt;code&gt;this&lt;/code&gt; is automagically bound to the component instance for you. Those of you who used React in the early days may remember how painful keeping track of the scope of &lt;code&gt;this&lt;/code&gt; could be. Vue made this easy by taking care of the scope for you. Ensuring that referencing &lt;code&gt;this&lt;/code&gt; in your methods, computed properties, or even lifecycle hooks, was always bound to the component instance. This was great, as it greatly reduced cognitive overhead when working inside a component and it really lowered the barrier to entry for more inexperienced devs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// WHAT?! In normal JS "this" would not be what you think it is&lt;/span&gt;
                         &lt;span class="c1"&gt;// but Vue takes care of that for you&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;The drawback of course to all of this was the extra work that had to be done to add proper type inference. Plugin authors had to jump through extra hoops, and TypeScript devs using Vue often resorted to using a &lt;a href="https://class-component.vuejs.org/"&gt;community package&lt;/a&gt; that added decorators to classes and properties. Now, if you opt to use the composition API, there is no need for this extra legwork since you're working with more natural and type-friendly Javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;  &lt;span class="c1"&gt;// note, you have to use ".value" to access it now&lt;/span&gt;
                        &lt;span class="c1"&gt;// but you no longer have to worry about what "this" actually is!&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;
  
  
  Organization of code logic
&lt;/h2&gt;

&lt;p&gt;This is a huge one for me, as I've seen just how out of control a component can get at scale.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Well, that shouldn't have ever happened. If you were using components correctly, you would've abstracted more of the logic into separate components to keep the original component simple.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Shut up, Karen. No one asked you.&lt;/p&gt;

&lt;p&gt;Really though, sometimes things happen and components get huge. Like &lt;a href="https://github.com/vuejs/vue-cli/blob/a09407dd5b9f18ace7501ddb603b95e31d6d93c0/packages/@vue/cli-ui/src/components/folder/FolderExplorer.vue#L198-L404"&gt;this one&lt;/a&gt;, referenced in the Composition API overview.&lt;br&gt;
When components do inevitably get out of control like this, it gets &lt;em&gt;really&lt;/em&gt; hard to understand what is going on. Logic can become fragmented because you have your data being declared at the top, but the method that uses that data is &lt;em&gt;all the way&lt;/em&gt; at the bottom, and maybe that method references a computed property somewhere in the middle.. you see where I'm going with this.&lt;br&gt;
The more you have to navigate up and down a file, the more cognitive load you're enduring. &lt;a href="https://smile.amazon.com/Dont-Make-Think-Revisited-Usability/dp/0321965515/ref=sr_1_1?dchild=1&amp;amp;keywords=don%27t+make+me+think&amp;amp;qid=1594500153&amp;amp;sr=8-1"&gt;If users shouldn't have to think&lt;/a&gt;, why should we willingly endure such strain when we're just trying to understand wtf is going on?!&lt;/p&gt;

&lt;p&gt;Since the composition API doesn't rely on organization by component options, you're free to organize your code by logic. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// options API&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&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;prevCount&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;count&lt;/span&gt; &lt;span class="o"&gt;&amp;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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="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;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Composition API&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;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prevCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously, this is a small example, but you can see how this would really help clear things up. You can group your code into blocks based on what they're doing and you can focus all your attention on the block you're currently working in. It's like would you rather:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Declare a variable right before the function that is going to use it&lt;/li&gt;
&lt;li&gt;  Declare all variables at the top of a file and then all functions at the bottom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you chose the latter, then.. well. Sorry 'bout ya. 😜&lt;/p&gt;

&lt;h2&gt;
  
  
  Code reuse
&lt;/h2&gt;

&lt;p&gt;Lastly, there is code reuse. For a while now, the best way to share code among various components were mixins. Essentially, a mixin is a Vue object that exposes all the component lifecycle hooks and properties you might need, but it can be merged with another component.&lt;/p&gt;

&lt;p&gt;This is really cool because if you have the same type of initialization logic, or perhaps several functions that you'd like to share between components, all you have to do is apply a mixin and you've got it! Of course, though, there were downsides.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If the mixin happens to have the same data property or method name as the component using it, the mixin's options would be overwritten during the merge.&lt;/li&gt;
&lt;li&gt;  If you're a new developer, or just a different member of the team looking at a component that someone else wrote, it might not really be clear where some of the properties and methods are coming from.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The composition API solves spectacularly solves this. Since you're essentially writing basic JavaScript, you can simply export your data as a function and import it elsewhere! Now if you're calling a method, &lt;code&gt;unicornPoop()&lt;/code&gt;, somewhere in your component - you won't be confused as to where it came from, because you'll have an import statement at the top of the file. :chefs-kiss:&lt;/p&gt;

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

&lt;p&gt;The composition API looks to be an exciting new way for experienced Vue developers to write their components, and I really look forward to using it.&lt;/p&gt;

&lt;p&gt;What about you? Are you planning to use it? Will they pry the options API from your cold, dead, hands? Are you going to use them both? (yes, that's possible.)&lt;/p&gt;

&lt;p&gt;I'd love to hear about it! Be sure to follow me on twitter &lt;a href="https://twitter.com/_ronini"&gt;@_ronini&lt;/a&gt; and @ me all you want!&lt;/p&gt;

&lt;p&gt;Until next time 🖖🏻&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>100daysofcode</category>
    </item>
    <item>
      <title>Getting set up with Gridsome</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Thu, 09 Jul 2020 18:32:30 +0000</pubDate>
      <link>https://forem.com/_ronini/getting-set-up-with-gridsome-2ai0</link>
      <guid>https://forem.com/_ronini/getting-set-up-with-gridsome-2ai0</guid>
      <description>&lt;p&gt;⚠️This article is a little heavier than some of the others. I found it best to try and explain the basic structure in a fair amount of detail, but feel free to skim to sections that catch your attention!⚠️&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;So first things first, we need to actually install Gridsome. Like most modern JS frameworks, they have a nice CLI tool we can use to get the project quickly set up.&lt;/p&gt;

&lt;p&gt;First install the Gridsome CLI,&lt;br&gt;
&lt;code&gt;npm i -g @gridsome/cli&lt;/code&gt;&lt;br&gt;
&lt;code&gt;yarn global add @gridsome/cli&lt;/code&gt; (gridsome recommends yarn)&lt;/p&gt;

&lt;p&gt;Then all we have to do is create a new project straight from the CLI!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gridsome create ronini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd ronini&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we can start the server &lt;code&gt;gridsome develop&lt;/code&gt; and navigate to &lt;code&gt;localhost:8080&lt;/code&gt; in your browser to view your site live. Pretty simple! 🥳&lt;/p&gt;
&lt;h2&gt;
  
  
  Directory Structure
&lt;/h2&gt;

&lt;p&gt;Now lets take a look around and get ourselves familiar with what Gridsome has set us up with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk0l7pxpm2tibn948b9cs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk0l7pxpm2tibn948b9cs.png" alt="Directory Structure" width="370" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, I won't go over &lt;em&gt;everything&lt;/em&gt; because there is a lot going on here and Gridsome, like most tools in the Vue ecosystem, has pretty stellar docs, which you can find &lt;a href="https://gridsome.org/docs"&gt;here&lt;/a&gt;. I will go over some of the bigger talking points though.&lt;/p&gt;
&lt;h3&gt;
  
  
  Main.js
&lt;/h3&gt;

&lt;p&gt;As you'll see with most of the files and folders in your newly bootstrapped project, the Gridsome team has done a great job of trying to outline the basics for everything. If you open up &lt;code&gt;main.js&lt;/code&gt; , you should see something similar to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftn3wcvbwza9afv8u5gpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftn3wcvbwza9afv8u5gpw.png" alt="Main.js file" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few things to note here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We're importing and registering a component called &lt;code&gt;DefaultLayout&lt;/code&gt; globally. This is something called.. well.. a &lt;strong&gt;layout&lt;/strong&gt; and we will talk about them very shortly.&lt;/li&gt;
&lt;li&gt;As the comments suggest, if we wanted to register components/filters/directives with the Vue instance, this is where we would do it. This is also where we would import a global css file, which we will also do in another article.&lt;/li&gt;
&lt;li&gt;You can see scripts mentioned as a potential import here. This is where you would inject things into the head of your document such as font awesome, google analytics, etc. (You might also be able to find a plugin for that - another topic we will discuss in a later article.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  /layouts
&lt;/h3&gt;

&lt;p&gt;Let's go ahead and move into the layouts directory since we've already mentioned a layout component. Layouts are basically just large wrapper components that you can use to define the &lt;em&gt;layout&lt;/em&gt; of certain pages, routes, or even your whole site.&lt;/p&gt;

&lt;p&gt;If you open up &lt;code&gt;/layouts/Default.vue&lt;/code&gt;, and take a look at the code inside the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tags, you should see&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdyrw3ntsqiyhy2eurbm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdyrw3ntsqiyhy2eurbm8.png" alt="Default Layout component" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we have a few cool things happening here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see a component here, &lt;code&gt;g-link&lt;/code&gt;, that is Gridsome's wrapper around Vue-Router's &lt;code&gt;router-link&lt;/code&gt;. It really acts the same way, but with the added benefit of prefetching data from those links using intersection observers. What this means, is if the link is in view, Gridsome will make the request in the background and grab all that data for the user. This way, when the user clicks the link, the transition is almost instantaneous. This is how sites like Gridsome and Gatsby make the user experience feel so fast when they're navigating around the site.&lt;/li&gt;
&lt;li&gt;You'll probably also notice the &lt;code&gt;$static.metadata.siteName&lt;/code&gt;, which is a topic for another time but the basics of it is this; Gridsome uses GraphQL under the hood to organize data. This allows you to write GraphQL queries in your components to fetch relevant data and present it like so. Here, we have fetched the name of our site from the &lt;code&gt;metadata&lt;/code&gt; object. Pretty cool stuff! If you want to learn more about it, you can check the docs &lt;a href="https://gridsome.org/docs/data-layer/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lastly, we have a &lt;code&gt;slot&lt;/code&gt; component. If you're unfamiliar with Vue slots, they are a way to create components that can be passed children. For example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// CoolTitleComponent.js&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&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;header&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'awesomeHeader'&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;h1&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'awesomeHeader--text'&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;slot&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;slot&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;h1&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;header&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;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Somewhere else in our app&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CoolTitleComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Wassssuppppp
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CoolTitleComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;In this example, we have a component called &lt;code&gt;CoolTitleComponent&lt;/code&gt; , which contains a component provided to us by Vue, called &lt;code&gt;slot&lt;/code&gt;. In this component we can do whatever we want, but for example sake let's just say our component applies some cool color to the text (purple, because it's the best) placed in our &lt;code&gt;h1&lt;/code&gt; tag. Then somewhere else in our app we use our component and place the text "Wassssupppppp" in between the opening and closing tags, because why not.&lt;/p&gt;

&lt;p&gt;When Vue renders this component, the &lt;code&gt;slot&lt;/code&gt; component will be replaced with the text that we passed in, and our component will be rendered as :&lt;br&gt;
&lt;/p&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;header&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'awesomeHeader'&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;h1&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'awesomeHeader--text'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  
      Wassssuppppp
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Slots are super powerful, and I would definitely recommend reading more about them &lt;a href="https://vuejs.org/v2/guide/components-slots.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So for our &lt;code&gt;Default&lt;/code&gt; component, this means that we can structure anything that is passed in the way we see fit! With the code provided to you by the CLI, you can wrap any component you make inside of the &lt;code&gt;Default&lt;/code&gt; component, and it will always render with a nav bar as seen in the code, as well as some global styles! We will be editing this file in our next article, so stay tuned 📺.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Index.html and App.vue (optional)
&lt;/h3&gt;

&lt;p&gt;I'm going to group these two files together because they are both optional. Normally when creating a new Vue application you'd have &lt;code&gt;App.vue&lt;/code&gt; as the root of all components, and the main entry point. Gridsome, by default, takes care of this under the hood. However, you can override the default file by creating one of your own if you just create an &lt;code&gt;App.vue&lt;/code&gt; file in the root of your &lt;code&gt;src&lt;/code&gt; directory. We will be doing this to apply global transition effects to our app later on.&lt;/p&gt;

&lt;p&gt;Index.html is handled the same way by Gridsome, and can be overridden by creating an &lt;code&gt;index.html&lt;/code&gt; file in the root of your &lt;code&gt;src&lt;/code&gt; directory as well. This probably won't be used as often, as you can actually inject scripts and cdn links via the &lt;code&gt;main.js&lt;/code&gt; file as we discussed earlier. However, if that can't be done, or you'd just rather not do it that way, you can override the &lt;code&gt;index.html&lt;/code&gt; and insert the content that way instead!&lt;/p&gt;

&lt;h3&gt;
  
  
  /static
&lt;/h3&gt;

&lt;p&gt;This one is fairly straight forward. Any files and directories you place here will be copied straight to the &lt;code&gt;/dist&lt;/code&gt; folder during build time. This is where you'd put something like a font file that you're serving yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  /pages
&lt;/h3&gt;

&lt;p&gt;This directory is where you put all your, you guessed it, &lt;strong&gt;pages!&lt;/strong&gt; Here you'll create &lt;code&gt;.vue&lt;/code&gt; files that are various pages in your application. Any file you put here, Gridsome will automagically create a route for! So in the generated code we have:&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="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means Gridsome has generated two routes for us, &lt;code&gt;/&lt;/code&gt; (index.vue, this is the root of the site), and &lt;code&gt;/about&lt;/code&gt;. Now can navigate to these routes in your browser like &lt;code&gt;localhost:8080/about&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;So we can see how it works, lets go ahead and create a new file in our &lt;code&gt;/pages&lt;/code&gt; directory called &lt;code&gt;Blog.vue&lt;/code&gt;. We'll put this into the file,&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;template&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="nc"&gt;Layout&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;
        This is my blog!!
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&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;template&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;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    export default &lt;span class="si"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save your changes, and navigate to &lt;code&gt;[localhost:8080/blog](http://localhost:8000/blog)&lt;/code&gt; in your browser. You should see your page load!&lt;/p&gt;

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

&lt;h3&gt;
  
  
  /templates
&lt;/h3&gt;

&lt;p&gt;Straight from the Gridsome docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Templates are used to create single pages for nodes in a collection. Nodes need a corresponding page in order to be presented on its own URL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now... some of you might have understood that. I wasn't one of those people - so let me try and explain in a way that I now understand.&lt;/p&gt;

&lt;p&gt;If you are connecting your site to an external data source, say something like Contentful, Netlify CMS, or Wordpress, You would use templates to generate pages based on the data received from those data sources. &lt;/p&gt;

&lt;p&gt;Still doesn't make sense? That's okay! Think of it like this:&lt;/p&gt;

&lt;p&gt;Let's pretend you have a blog. The content of that blog is written using Netlify CMS and displayed on your Gridsome site. If the data of each of your posts (the headings, text, pictures, etc.) were all different flavors of Ben &amp;amp; Jerry's Ice Cream (Try Netflix and Chill'd, tweet @ me when you do 😋), then the container would be the template! The content might all change from from post to post, but they'll all have the same structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd64nacrlghfel2e7n2la.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd64nacrlghfel2e7n2la.png" alt="Ben &amp;amp; Jerry's Ice Cream" width="400" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Okay.. but didn't you say this is what &lt;code&gt;Layouts&lt;/code&gt; are for..? - you, probably.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes.. and no. Layout do &lt;em&gt;theoretically&lt;/em&gt; do the same thing, but for different types of data. A layout is something you apply manually to your components, to structure any content inside. A &lt;strong&gt;template&lt;/strong&gt; is &lt;strong&gt;also&lt;/strong&gt; a way to structure content, but it is applied &lt;strong&gt;automatically&lt;/strong&gt; to certain types of content. In this case, a blog post.&lt;/p&gt;

&lt;p&gt;This does require some manual configuration which you can learn about &lt;a href="https://gridsome.org/docs/templates/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was part 2 in my series about rebuilding my personal site with Gridsome! I know this one wasn't quite as exciting, but next time we will go over plugins in Gridsome, and we will add my favorite CSS framework, Tailwind CSS! See you all next time, and be sure to follow me on &lt;a href="https://twitter.com/_ronini"&gt;twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>gridsome</category>
      <category>vue</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Rebuilding my personal site with Gridsome</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Thu, 18 Jun 2020 13:07:45 +0000</pubDate>
      <link>https://forem.com/_ronini/rebuilding-my-personal-site-with-gridsome-28bc</link>
      <guid>https://forem.com/_ronini/rebuilding-my-personal-site-with-gridsome-28bc</guid>
      <description>&lt;p&gt;I've decided to Rebuild my personal site with Gridsome for a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I've learned quite a lot since making it just a year ago.&lt;/li&gt;
&lt;li&gt;It's lacking in content, and I don't feel as though it showcases everything I think is important.&lt;/li&gt;
&lt;li&gt;My contact section isn't &lt;strong&gt;obvious&lt;/strong&gt; enough.&lt;/li&gt;
&lt;li&gt;I don't imagine it's SEO optimized.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll be documenting this process along with my train of thought and decisions along the way. I hope that at least some of you can get something out of it! If nothing else, I'll have a cool little reminder of this process that I can look back on in the future. 😃&lt;/p&gt;

&lt;h2&gt;
  
  
  So Why Gridsome?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyeq5sadxv3265n70vody.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyeq5sadxv3265n70vody.jpeg" alt="Gridsome Logo" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;A lot of you may not have heard of &lt;strong&gt;&lt;a href="https://gridsome.org"&gt;Gridsome&lt;/a&gt;&lt;/strong&gt; as it's still in it's early days (0.7.17 at the time of writing), so what is it?&lt;/p&gt;

&lt;p&gt;To put it simply, it's &lt;strong&gt;Gatsby&lt;/strong&gt; for &lt;strong&gt;Vue&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SSG (static site generator) Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Straight from the &lt;a href="https://gridsome.org"&gt;home page&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Gridsome makes it easy for developers to build static generated websites &amp;amp; apps that are fast by default 🚀&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Fast by default&lt;/strong&gt;. This is one of the main reasons for picking an SSG like Gridsome or Gatsby. They come with so many out-of-the-box optimizations that you get 90+ lighthouse scores from the start. This can be a huge timesaver, and who doesn't like fast sites?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSG's allow you to work with lots of convenient tools such as templating engines, and transforming markdown files into HTML pages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They're easy to deploy, and with the help of providers like &lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt;, you can even deploy them for free within minutes! Netlify even lets you connect to your github repo and it'll automatically re-build and deploy everytime you push a change!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Of course, they're more secure as well. Without a server, there are fewer points in which to exploit.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gridsome VS Gatsby
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnbxdnr1p11esa4t80dc6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnbxdnr1p11esa4t80dc6.jpeg" alt="Gridsome vs Gatsby" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
image from &lt;a href="https://morioh.com/p/b8b12d6aa29a"&gt;morioh.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Put your pitchforks down, I'm not here to tell you one is better than the other. Only outline the differences and explain why I chose Gridsome.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The most important and obvious reason - I'm a Vue developer. I fell in love with Vue a little over a year ago, starting using it for side projects, and now I use it at work! With Gatsby being a React-based SSG, I opted to stick with what I know and enjoy purely because of my personal bias. I've used React in the past, and it'll always hold a special place in my heart - but I'm just much faster and more productive in Vue.&lt;/li&gt;
&lt;li&gt;Gridsome actually takes most of it's inspiration from Gatsby such as

&lt;ul&gt;
&lt;li&gt;Plugins&lt;/li&gt;
&lt;li&gt;Themes (starters in Gridsome)&lt;/li&gt;
&lt;li&gt;GraphQL data layer for cool things like site metadata, images, and page queries (something we will talk more in depth about in a later post)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these things make it a joy to work with and really which one you choose comes down to either personal bias, or your desire to use something more mature (Gatsby being around for much longer at this point)&lt;/p&gt;

&lt;p&gt;Our journey starts here! In the next post we'll talk more about getting started with Gridsome, along with some basic project configuration.&lt;/p&gt;

&lt;p&gt;See you then 🖖&lt;/p&gt;

</description>
      <category>vue</category>
      <category>gridsome</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Greatest Strength and Greatest Weakness</title>
      <dc:creator>Ronnie Villarini</dc:creator>
      <pubDate>Mon, 22 Jul 2019 11:43:09 +0000</pubDate>
      <link>https://forem.com/_ronini/greatest-strength-and-greatest-weakness-5b1p</link>
      <guid>https://forem.com/_ronini/greatest-strength-and-greatest-weakness-5b1p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;What is your greatest strength? What about your greatest weakness?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've been to an interview, chances are that you have heard this question at least once.&lt;br&gt;
I'm going to tell you a secret:&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;hate&lt;/strong&gt; it&lt;/p&gt;

&lt;h2&gt;
  
  
  It's Not A Bad Interview Question
&lt;/h2&gt;

&lt;p&gt;I feel as though it is important for me to preface this by saying, I don't hate it because it's just a bad question. I hate it because my greatest weakness is &lt;strong&gt;also&lt;/strong&gt; my greatest strength. For me, I believe this is my "all or nothing" personality.&lt;/p&gt;

&lt;h2&gt;
  
  
  WUT?
&lt;/h2&gt;

&lt;p&gt;What does that even mean, Ronnie? Well, for the longest time I didn't realize it - but I'm incapable of just "dipping my toes in". Regardless of if the subject is video games, cooking, or coding - I go, for lack of a better word, &lt;strong&gt;H.A.M.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Good
&lt;/h2&gt;

&lt;p&gt;Going so overboard on just about any topic that really catches my interest gives me a lot of obvious benefits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I am able to really focus on the topic at hand&lt;/li&gt;
&lt;li&gt;  I end up learning a lot, from a large variety of resources&lt;/li&gt;
&lt;li&gt;  I learn at a very accelerated pace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, if I hadn't been this way, I likely wouldn't have been able to make the career change from my seven years at Walmart to a professional developer in under 6 months. Since I was so hyper-focused and well, &lt;strong&gt;obsessed&lt;/strong&gt;, I was able to give up a lot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I have been a huge gamer since I was around 7, and I gave up gaming for that 6 months&lt;/li&gt;
&lt;li&gt;  I spent all of my free time studying and practicing.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Work -&amp;gt; Family Time -&amp;gt; Code&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Bad
&lt;/h2&gt;

&lt;p&gt;So, what's so bad about that? Sounds like it worked out pretty well for me, right? I succeeded in making the career change, and now I'm working for an awesome company doing something I love.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  At some point, you start to forget who you are&lt;/li&gt;
&lt;li&gt;  It gets easy to become so focused, it starts to interfere with other responsibilities&lt;/li&gt;
&lt;li&gt;  It can become unhealthy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whoa, Whoa, Whoa. Let's start from the top, "forget who you are"?? Yes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Forgetting Who You Are
&lt;/h3&gt;

&lt;p&gt;In fear of sounding dramatic, at some point you &lt;strong&gt;can&lt;/strong&gt; get lost in what you're doing at lose track of who you are. As I said before, I was, and still am, a &lt;strong&gt;huge&lt;/strong&gt; gamer. Video games for me, like many others, have been an awesome way to escape. When things in life weren't great and when I just needed a little distraction or an experience, games were always there.&lt;/p&gt;

&lt;p&gt;When I made the dive into coding and making this career switch, I gave that up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I forgot to take &lt;strong&gt;breaks&lt;/strong&gt; sometimes. (Those are &lt;em&gt;really&lt;/em&gt; important.)&lt;/li&gt;
&lt;li&gt;  It became more difficult for me to cope with my &lt;a href="https://www.webmd.com/depression/guide/bipolar-disorder-manic-depression#1"&gt;manic depression&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Interfering With Other Responsibilities
&lt;/h3&gt;

&lt;p&gt;I am a father of &lt;strong&gt;two&lt;/strong&gt; beautiful girls, and I am lucky enough to have met a woman that I &lt;strong&gt;intend&lt;/strong&gt; on spending the rest of my life with (shhh 🤫, I haven't proposed yet). So, what does that have to do with anything?&lt;/p&gt;

&lt;p&gt;Well, when I became blinded by my ambition and desires, I neglected some of my other responsibilities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I was not spending enough time with my daughter (my youngest hadn't been born yet)&lt;/li&gt;
&lt;li&gt;  Sammie and I sacrificed our time together as a couple, and sometimes she sacrificed her spare time to take care of our oldest so that I could get more studying in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a big deal, and it's something I will forever be thankful for. I wouldn't have made it this far without the help and support I received from Sammie. Now, I do my best to make up for that lost time and try and not get so blinded in the future. This could have easily cost me my relationship.&lt;/p&gt;

&lt;h2&gt;
  
  
  It Can Become Unhealthy
&lt;/h2&gt;

&lt;p&gt;Yeah, Yeah, Yeah - I know. This is probably stretching it for a lot of you. As I said though, this is my experience and has a lot to do with my own addictive personality.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I stopped eating regularly, and definitely wasn't eating as healthily       - only food that allowed me to get back to studying as quickly as possible&lt;/li&gt;
&lt;li&gt;  I stopped exercising, or really anything that would take away from the limited time I had to study&lt;/li&gt;
&lt;li&gt;  I sacrificed as much sleep as I could while still maintaining the ability to minimally function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I made cuts the same way a corporation does. I sacrificed anything that took away from my ability to study and saw it as something that just wasn't important right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's Okay To Be Passionate
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow your heart, but take your brain with you.&lt;/p&gt;

&lt;p&gt;~ Haley Michael (an old friend of mine)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm not trying to say it's not okay to keep your nose down and really give something your all.&lt;br&gt;
That's a wonderful thing to do, and it is a great way to accomplish your goals! Just be conscious of what you're doing. Not everyone gets this obsessed with things, and most are more than capable of drawing that line for themselves.&lt;/p&gt;

&lt;p&gt;This is just simply &lt;strong&gt;my&lt;/strong&gt; greatest strength &lt;strong&gt;and&lt;/strong&gt; weakness.&lt;/p&gt;

&lt;p&gt;What is your greatest strength and greatest weakness? I'd love to hear what you have to say.&lt;/p&gt;

&lt;p&gt;You can find me on &lt;a href="https://twitter.com/_Ronini"&gt;Twitter&lt;/a&gt;, &lt;a href="https://dev.to/_ronini"&gt;Dev.to&lt;/a&gt;, &lt;a href="https://www.instagram.com/ka0sronnie/?hl=en"&gt;Instagram&lt;/a&gt;,&lt;br&gt;
and &lt;a href="https://www.linkedin.com/in/ronnievillarini/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading! 👋🏻✌️&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>discuss</category>
      <category>career</category>
      <category>interview</category>
    </item>
  </channel>
</rss>
