<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Steve Edwards</title>
    <description>The latest articles on DEV Community by Steve Edwards (@wonder95).</description>
    <link>https://dev.to/wonder95</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%2F354179%2Fa4164d9b-5b58-49e7-8734-1822ab2c7344.jpeg</url>
      <title>DEV Community: Steve Edwards</title>
      <link>https://dev.to/wonder95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wonder95"/>
    <language>en</language>
    <item>
      <title>Dynamically Importing Vuex Store Modules From Directory Structure</title>
      <dc:creator>Steve Edwards</dc:creator>
      <pubDate>Sun, 03 May 2020 18:09:06 +0000</pubDate>
      <link>https://dev.to/wonder95/dynamically-importing-vuex-store-modules-from-directory-structure-o54</link>
      <guid>https://dev.to/wonder95/dynamically-importing-vuex-store-modules-from-directory-structure-o54</guid>
      <description>&lt;p&gt;This is a continuation of my &lt;a href="https://dev.to/wonder95/dynamically-generating-vue-router-routes-from-directory-structure-1g8"&gt;previous post&lt;/a&gt;, where I went through the details of how to define Vue router route definitions in files throughout the app directory structure, and then import them into the main router &lt;code&gt;index.js&lt;/code&gt; file. In this post, I'm going to be showing the same process for Vuex store modules. There are a couple small variations from the router import code, but nothing major.&lt;/p&gt;

&lt;p&gt;First, here is the structure of a store module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as types from '@/store/types';

const state = {
  events: [],
};

// getters
const getters = {
  getEvents: state =&amp;gt; state.events,
};

// actions
const actions = {

};

// mutations
const mutations = {
  [types.SET_EVENTS](state, shifts) {
    state.events = shifts;
  }
};

export default {
  namespaced: true,
  name: 'event',
  state,
  getters,
  actions, 
  mutations
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is one small addition to this file for import purposes, and that is the &lt;code&gt;name&lt;/code&gt; key in the exported object. This is because during the import process, since stores are separated by namespaces, a &lt;code&gt;name&lt;/code&gt; property is needed. However, in looking through all of the available information returned from &lt;code&gt;require.context()&lt;/code&gt;, I didn't see the value of the parent directory name, so I just added that value to the exported object.&lt;/p&gt;

&lt;p&gt;With those defined, here is the store index.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Vue from 'vue';
import Vuex from 'vuex';
import Auth from '@/store/modules/auth'

Vue.use(Vuex);

const debug = process.env.NODE_ENV !== 'production';

Vue.config.devtools = true;

// Import all of the resource store files.
function loadStores() {
  const context = require.context('@/resources', true, /store.js$/i);
  return context.keys()
    .map(context)         // import module
    .map(m =&amp;gt; m.default)  // get `default` export from each resolved module
}

const resourceModules = {};
loadStores().forEach((resource) =&amp;gt; {
  resourceModules[resource.name] = resource;
});

resourceModules.auth = Auth;

export default new Vuex.Store({
  modules: resourceModules,
  strict: debug,
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see where I use the exported name property in the call to &lt;code&gt;loadStores()&lt;/code&gt;. Then, once all of the store modules under the &lt;code&gt;/resources&lt;/code&gt; directory are adde to the &lt;code&gt;resourceModules&lt;/code&gt; object, I manually add the store for the &lt;code&gt;Auth&lt;/code&gt; module (since it's outside of the &lt;code&gt;/resources&lt;/code&gt; directory), and then pass it all to the &lt;code&gt;modules&lt;/code&gt; key in the &lt;code&gt;new Vuex.Store()&lt;/code&gt; constructor. After verifying in the Vue Dev tools that the store exist, I'm off and running. &lt;/p&gt;

</description>
      <category>vue</category>
      <category>vuex</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Dynamically Generating Vue Router Routes From Directory Structure</title>
      <dc:creator>Steve Edwards</dc:creator>
      <pubDate>Sun, 03 May 2020 18:00:29 +0000</pubDate>
      <link>https://dev.to/wonder95/dynamically-generating-vue-router-routes-from-directory-structure-1g8</link>
      <guid>https://dev.to/wonder95/dynamically-generating-vue-router-routes-from-directory-structure-1g8</guid>
      <description>&lt;p&gt;I'm working on a Vue starter kit for a Javascript platform that I've used for a few years, and I have the need - well, the desire to make it as easy for the developer as possible - to automatically import route definitions from multiple locations and add them to the Router() definition, instead of loading them all from the router index file.&lt;/p&gt;

&lt;p&gt;In applications such as Vue apps that have multiple types of files that are used together to create the app, there are primarily two ways to organize the files. For instance, in Vue, let's say that we have multiple resources, and each resource has three components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The component (.vue file)&lt;/li&gt;
&lt;li&gt;The router definition file&lt;/li&gt;
&lt;li&gt;The Vuex module file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could choose to organize your files in two different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By feature - each directory has a .vue file, a router file, and a Vuex file&lt;/li&gt;
&lt;li&gt;By functionality - one directory each for components, one for router files, and one for Vuex files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my case, I'm going to group by feature, which I will refer to as a resource (to match the platform naming convention). Using the example resources, of user, event, and job, this will be my directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
  |
  ---/resources
         |
         ---/user
              |
               ---User.vue
               ---routes.js
               ---store.js
            /event
              |
               ---Event.vue
               ---routes.js
               ---store.js
            /job
              |
               ---Job.vue
               ---routes.js
               ---store.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The contents of a &lt;code&gt;routes.js&lt;/code&gt; file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Event from '@/resources/event/Event'

export default [
  {
    path: '/events',
    name: 'event',
    component: Event
  },
];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Including an additional &lt;code&gt;Auth.vue&lt;/code&gt; component (which is outside the &lt;code&gt;/resources&lt;/code&gt; directory), our base router index file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Auth from '@/components/Auth';

Vue.use(Router);

let routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/login',
    name: 'auth',
   component: Auth
  },
];

export default new Router({
  mode: 'history',
  routes,
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If I were to manually add the router objects for my three resources, I could do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Auth from '@/components/Auth';
import Event from '@/resources/event/Event';
import Job from '@/resources/job/Job';
import User from '@/resources/user/User'; 

Vue.use(Router);

let routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/login',
    name: 'auth',
    component: Auth
  },
  {
    path: '/events,
    name: 'event',
    component: Event
  },
  {
    path: '/Job',
    name: 'job',
    component: Job
  },
  {
    path: '/user',
    name: 'user',
    component: User
  },
];

export default new Router({
  mode: 'history',
  routes,
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;However, I want to avoid having to manually update this file every time I add a resource, so instead I do it dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import Auth from '@/components/Auth';

Vue.use(Router);

let baseRoutes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/login',
    name: 'auth',
    component: Auth
  },
];

// Import all of the resource routes files.
function loadRoutes() {
  const context = require.context('@/resources', true, /routes.js$/i)
  return context.keys()
    .map(context) // import module
    .map(m =&amp;gt; m.default) // get `default` export from each resolved module
}

const resourceRoutes = loadRoutes();
resourceRoutes.forEach((route) =&amp;gt; {
  routes.push(route[0]);
});

export default new Router({
  mode: 'history',
  routes,
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The magic happens in the &lt;code&gt;loadRoutes()&lt;/code&gt; function. As described to me in the &lt;a href="https://stackoverflow.com/a/61262665/391054"&gt;answer to my Stackoverflow post&lt;/a&gt;, &lt;code&gt;require.context()&lt;/code&gt; returns a context module, which exports a &lt;code&gt;keys&lt;/code&gt; function that returns an array of all possible requests (i.e., the matching paths), each of which could be passed to the context itself (which invokes its resolve function) to import the corresponding module. The returned array from &lt;code&gt;loadRoutes()&lt;/code&gt; function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resourceRoutes = [
  {
    0: [
          {
            path: "/event",
            name: "event",
           component: {
             name: "Event",
             ...
           }
        ]
  },
  {
    1: [
          {
            path: "/jobs",
            name: "job",
           component: {
             name: "Job",
             ...
           }
        ]
  },
...
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;so I just loop through each returned item, get the first array item, and add it to the routes array. And voila!, it's done.&lt;/p&gt;

&lt;p&gt;There are a couple benefits to this approach. First, it keeps my code modularized and keeps my main router file from getting more and more cluttered. Second, this looks toward the future; down the road, I will be creating a Vue CLI plugin that will allow a user to add all of the necessary files for a new resource that has been added to the platform, and it is easier to create a new file with a pre-determined content than it is to modify the contents of an existing file.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Creating a Fast Site with Nuxt and CSS</title>
      <dc:creator>Steve Edwards</dc:creator>
      <pubDate>Mon, 23 Mar 2020 04:14:38 +0000</pubDate>
      <link>https://dev.to/wonder95/creating-a-fast-site-with-nuxt-and-css-3d4o</link>
      <guid>https://dev.to/wonder95/creating-a-fast-site-with-nuxt-and-css-3d4o</guid>
      <description>&lt;p&gt;As a developer who has spent the majority of his years working on the back end of website projects, my front end skills have not always been very developed, to put it mildly. At those times when I did need to do theming work, I would rely on tools like Bootstrap, Bulma, or Vuetify to handle the bulk of it for me. However, over the last year, after hearing so much about the features that have been added to HMTL and CSS over the past few years, I decided to start learning about CSS.&lt;/p&gt;

&lt;p&gt;In particular, CSS Grid and Flexbox intrigued me, because layout has always been fairly difficult, so I started out by taking the free courses from Wes Bos on &lt;a href="https://cssgrid.io/"&gt;Grid&lt;/a&gt; and &lt;a href="https://flexbox.io"&gt;Flexbox&lt;/a&gt;. I also want to be able to learn to design my own layouts, so I got Adam Wathan’s &lt;a href="https://refactoringui.com/"&gt;Refactoring UI&lt;/a&gt; (although I haven’t been able to get started on it yet).&lt;/p&gt;

&lt;p&gt;I was starting to look around for a project to work on, when I was presented with an opportunity to do a &lt;a href="https://cesf.us"&gt;website for a local non-profit&lt;/a&gt;. Still not feeling comfortable with designing my own theme, I went browsing on the internets and came across the &lt;a href="https://preview.themeforest.net/item/icare-nonprofit-fundraising-html-template/full_screen_preview/7974340"&gt;iCare theme&lt;/a&gt; on Theme Forest. After getting approval from the organization, I purchased the theme.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting the Site Toolset
&lt;/h2&gt;

&lt;p&gt;In this particular case, SEO was very important to the organization, and being familiar with the Vue ecosystem (I work with Vue in my day job), I decided to go with Nuxt, because of its server side rendering capabilities. For the back end, I looked at a couple of different options. I knew I wanted to use a headless CMS. I worked with Drupal for a number of years, so I’m very familiar with content modeling and structure, but I wanted something that I didn’t have to set up myself. I considered a GitHub pages-type structure where I write in markdown files and commit directly to a repository, but there were a couple problems with that. First, that would work great for me, but I am the only technical person in the organization, and if I were to get hit by the proverbial bus (or fire engine, &lt;a href="https://www.facebook.com/clackamasfire/photos/a.3985692881444509/3985697871444010/?type=3&amp;amp;theater"&gt;in my case&lt;/a&gt;) I wanted a non-technical person to be able to manage site content in my absence. I really like &lt;a href="https://buttercms.com"&gt;ButterCMS&lt;/a&gt; (the CMS I use for this site), because it has a very flexible data modeling and content management user interface, and the API is drop dead easy to use. However, in order to get the full data modeling capabilities, the cost is $99/month, and that was cost prohibitive for the organization. I started looking at the many hosted headless CMS options, and narrowed it down to Prismic, Sanity, Contentful, Zesty, and Strapi. After considering all the different pros and cons (cost, API ease of use, data modeling capabilities, etc) of each one, I decided to go with &lt;a href="https://prismic.io%5B"&gt;Prismic&lt;/a&gt;. The Content Query API takes a little getting used to, and the API docs can be a little confusing, but the UI is fairly intuitive and flexible, and it has good code documentation for various frameworks and languages (including VueJs and Nuxt). For just one user it is free, and adding two more users only costs $7/month, so that fit right in the organization’s budget.&lt;/p&gt;

&lt;p&gt;From a hosting standpoint, my own site is hosted in &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt;, and it is a popular and flexible platform that I am already familiar with, so choosing it was a no-brainer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Theme
&lt;/h2&gt;

&lt;p&gt;My initial plan with the iCare theme was to just incorporate it into Nuxt, add the data, and be off and running. However, the theme contains multiple other dependencies (much custom JS, jQuery, PopperJS, FontAwesome, etc.) and although I tried and tried, I could never get everything to work without a bunch of re-work. After banging my head against that for a while, I decided to build my theme from scratch with CSS Grid. So I started from the front page, and built it out, doing my best to make it look exactly like the iCare theme, but only in appearance, not underlying structure. After a while, I got the header, the footer, and the central content area complete in a full page format. However, it wasn’t responsive at all (you couldn’t even scroll to the side on a smaller screen), and although I had read about media queries and flexbox, I wasn’t sure exactly how to implement them in my theme.&lt;/p&gt;

&lt;p&gt;Instead of doing more head banging, I called on my friend &lt;a href="https://www.linkedin.com/in/illepic/"&gt;Chris Bloom&lt;/a&gt;. Chris is the Director of Frontend Engineering at &lt;a href="https://www.phase2technology.com/"&gt;Phase2 Technology&lt;/a&gt;, and a real CSS guru.  He and I go back to working in Drupal for Sony Music a few years ago, so I’ve known him for a while. He’s also a big proponent of &lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt;, and I’d recently seen him present on using it in &lt;a href="https://www.meetup.com/Portland-Vue-js-Meetup/events/267781079/"&gt;VueJS&lt;/a&gt;). I gave him access to my theme repo and said “can you make this responsive?”, and he said “sure!”, and a couple days later, sent me a merge request.&lt;/p&gt;

&lt;p&gt;I studied it for a while, made some changes, and got stuck, so Chris took an hour and a half and on a video call, and walked me through everything he had done (if you want to someone who is passionate about CSS, get Chris talking about CSS. Just sayin’.). The two things I learned from what he showed me were 1) using media queries and 1) Tailwind-type utility classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Media Queries
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"&gt;MDN&lt;/a&gt;, media queries “are useful when you want to modify your site or app depending on a device's general type (such as print vs. screen) or specific characteristics and parameters (such as screen resolution or browser &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/viewport"&gt;viewport&lt;/a&gt; width).” In this particular case, we just defined four queries that were minimum width sizes (borrowed from Tailwind’s breakpoints):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@media (min-width: 640px) {
  .container {
    max-width: 640px;
  }
}

@media (min-width: 768px) {
  .container {
    max-width: 768px;
  }
}

@media (min-width: 1024px) {
  .container {
    max-width: 1024px;
  }
}

@media (min-width: 1280px) {
  .container {
    max-width: 1280px;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The thing that it took me a while to get my head around was that for any of these queries, because we were only using &lt;code&gt;min-width&lt;/code&gt;, the styles used in that media query would apply for any size up to full screen size, unless overridden in another query of a higher size. For instance, in the example above, if there had been no &lt;code&gt;.container&lt;/code&gt; selected in the query for &lt;code&gt;min-width: 1024px&lt;/code&gt; or &lt;code&gt;1280px&lt;/code&gt;, the &lt;code&gt;max-width&lt;/code&gt; for the &lt;code&gt;.container&lt;/code&gt; class would be 768px. What this also means is that there are actually 5 sizes; the four sizes listed above, and anything below 640px wide; namely, phones.&lt;/p&gt;

&lt;p&gt;A good example of where this comes into play is with the main nav bar. Typically, in order to get a row of menu items, you would create a list of items using &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; tags, and then set &lt;code&gt;display: inline-block&lt;/code&gt; (or even &lt;code&gt;display:flex&lt;/code&gt;) on the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements. However, in a mobile view, we want them stacked vertically, and since that is the default list structure, we don’t have to apply CSS to make that happen. Then, when the screen is wide enough that we do want them to be horizontal, we can use a media query to make them inline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@media (min-width: 768px) {
  .flex {
    display: flex;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I finally understood that this is what is meant by &lt;em&gt;mobile first design&lt;/em&gt;; designing for the smaller screen, and then adding things as your screen gets wider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utility Classes
&lt;/h2&gt;

&lt;p&gt;As I get it, the idea behind utility classes is that each class does only one thing, and the name reflects what it does. For instance, a simple example would be aligning text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.text-left {
  text-align: left;
} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, you just apply the classes to a given element as needed. The downside is that you get a longer list of classes for a given element, but at the same time, you can also tell what that class is doing, as compared to a class with many attributes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining Media Queries and Utility Classes
&lt;/h2&gt;

&lt;p&gt;Now we can combine media queries with utility classes to easily modify section widths depending on screen sizes. As an example, on the events details page, we have these elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="container"&amp;gt;
  &amp;lt;div class="content-area sm:flex justify-between"&amp;gt;
    &amp;lt;div class="event-content-left sm:w-2/3 md:w-770"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here is the CSS to go along with them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; @media (min-width: 640px) {
    .container {
      max-width: 640px
    }

  .sm\:flex {
    display: flex;
  }

  .sm\:w-1\/3 {
    width: 33%;
  }

  .sm\:w-2\/3 {
    width: 66%;
  }
}

@media (min-width: 768px) {
  .container {
    max-width: 768px;
  }

  .md\:w-1\/3 {
    width: 33%;
  }

  .md\:w-2\/3 {
    width: 66%;
  }

  .md\:w-770 {
    width: 770px;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here is what’s happening:&lt;/p&gt;

&lt;p&gt;At a screen width of 640-767px:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The width of &lt;code&gt;.container&lt;/code&gt; has a &lt;code&gt;max-width&lt;/code&gt; value of 640px.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;display: flex&lt;/code&gt; property is added to the &lt;code&gt;.content-area&lt;/code&gt; element.&lt;/li&gt;
&lt;li&gt;The width of the &lt;code&gt;.content-area&lt;/code&gt; element is set to 33%.&lt;/li&gt;
&lt;li&gt;The width of the &lt;code&gt;.event-content-left&lt;/code&gt; element is set to 66%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a screen width of 768-1023px:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The width of the &lt;code&gt;.event-content-left&lt;/code&gt; element is set to 770px.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.display:flex&lt;/code&gt; is still set.&lt;/li&gt;
&lt;li&gt;The width of the &lt;code&gt;.content-area&lt;/code&gt; element is still set to 33%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One interesting thing to note is the difference between the class declarations in CSS and applications in HTML for the &lt;code&gt;sm:&lt;/code&gt; and &lt;code&gt;md:&lt;/code&gt; classes; the &lt;code&gt;:&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt; characters have to be escaped in the CSS (&lt;code&gt;sm\:w-1\/3&lt;/code&gt;), but is not in the HTML (&lt;code&gt;sm:w-1/3&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Forms
&lt;/h2&gt;

&lt;p&gt;The one last feature I needed to implement was forms. Fortunately, Netlify has a &lt;a href="https://docs.netlify.com/forms/setup/"&gt;solution for forms&lt;/a&gt;. The basic gist is that you create your form as you normally would (in this case, in a .vue single file component), and then create a .html file that has only the HTML form content (in my case, I created them under the /static/form_dummy directory), Netlify finds that file and automagically handles it, &lt;a href="https://docs.netlify.com/forms/submissions/"&gt;saving the submissions in your site dashboard&lt;/a&gt;. You can also set up &lt;a href="https://docs.netlify.com/forms/notifications/#email-notifications"&gt;email notifications&lt;/a&gt; when a form is submitted. On top of that, they even provide spam protection using Akismet, along with additional protection using a &lt;a href="https://docs.netlify.com/forms/spam-filters/"&gt;honeypot field&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The end result is a very fast, lightweight, static &lt;a href="https://cesf.us"&gt;site&lt;/a&gt; that is cheap to host, and with an easy to manage content CMS. The primary benefit for me was that I was able to use the process of building the site to do a lot of learning about CSS Grid and Flexbox, media queries, utility classes, and how to put them all together. What added more satisfaction was that it wasn't just a learning project that I came up with; it was a very real website for a very real organization that does a lot of great things.&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>css</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
