CurateBot Devlog 2: First steps - cleaning up the boilerplate
Tags: devjournal, javascript, vue, serverless
Published: 2021-01-04 20:31:24

The first thing I'm going to do after setting up the boilerplate, is de-crapify it. The boilerplate comes with several pieces of demo material, but I don't want any of these in my project, so I want to remove everything and start from a cleaner blank slate. The code can be seen [here](https://github.com/meseta/curatebot/tree/85150e5a39c7adda48e5cdfe43df0a3cebc5c14d/web/src).

I'll go over these file-by-file. Recall, the current site looks like this:

![Boilerplate screenshot](https://dev-to-uploads.s3.amazonaws.com/i/nzz1bzqvzybqshvos5br.png)

# App.vue
This is our root component. This is the highest level of Vue component that we deal with, and is always loaded. So all the app-level stuff goes in here, namely the app-bar (and also, later on, the UI notifications).

Importantly, the router component needs to go in here; the router component is provided by vue-router, and will handle switching out the view depending on what URL we are on.

The original boilerplate file is [here](https://github.com/meseta/curatebot/blob/0bedad59d2320885fd867da5a9848ae2fd4a88e3/web/src/App.vue). Here it is, in short form (I've snipped out a bunch of stuff)

```vue
<template>
  <v-app>
    <v-app-bar
      app
      color="primary"
      dark
    >
      ... snip ...
    </v-app-bar>

    <v-main>
      <HelloWorld/>
    </v-main>
  </v-app>
</template>

<script lang="ts">
import Vue from 'vue';
import HelloWorld from './components/HelloWorld.vue';
export default Vue.extend({
  name: 'App',
  components: {
    HelloWorld,
  },
  data: () => ({
    //
  }),
});
</script>
```
There's a few things worth mentioning here. Firstly, the boilerplate defines a <v-app-bar>, this is the blue bar at the top of the screenshot. This [<v-app-bar>](https://vuetifyjs.com/en/components/app-bars/) component is provided by Vuetify, it contains all the styling for an application bar, and has many options for tuning its appearance, for example right now it's set to `dark` which causes the text to show up in white. I'm going to go with the default for now, and will adjust appearances later.

The boilerplate also sticks in a <HelloWorld> component which it imports from `components/HelloWorld.vue` this component is what's responsible for all the junk on the page. I'll describe that later.

Finally, the <script> part of this Vue component contains just your standard matter for defining a component, it's empty other than defining the name, and a list of imported components (i.e. HelloWorld).

I'm going to do four things to this file:

1. Strip out the <v-app-bar> and put that in its own component at `components/AppBar.vue`
1. Remove <HelloWorld> and delete the vue file, we don't want that in here
1. Switch to TypeScript, and simplify the notation using [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator) which is a slightly neater way of defining Vue components
1. Insert the <router-view> component back into it. This component is provided by vue-router. It's actually in the Vue boilerplate App.vue file before vuetify removes it when it installs it's own stuff.

The final code can be found [here](https://github.com/meseta/curatebot/blob/85150e5a39c7adda48e5cdfe43df0a3cebc5c14d/web/src/App.vue), and I'm reproducing it in it's entirety below:

```vue
<template>
  <v-app>
    <AppBar />

    <v-main>
      <v-container fluid>
        <router-view />
      </v-container>
    </v-main>

    <!-- <v-footer app>
    </v-footer> -->
  </v-app>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import AppBar from '@/components/AppBar.vue'

@Component({ components: { AppBar } })
export default class AppView extends Vue {}
</script>
```

As you can see, this is much cleaner already. Note I added but commented out a <v-footer> component. I'll add that later.

# router/index.ts
The router component, provided by vue-router, let's us switch out the view depending on the URL. The default routes provided is a `/` home path, and an `/about` path that loads in the `views/About.vue` component. We're going to delete this one as well since we don't need it.

The original content of the router is [here](https://github.com/meseta/curatebot/blob/0bedad59d2320885fd867da5a9848ae2fd4a88e3/web/src/router/index.ts)

```ts
  
import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes: Array<RouteConfig> = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router
```

The only change I'm making here is to comment out the `/about` path since it's not needed. The rest I'll leave for now, but as I add more views, I will add them to this router. The code is [here](https://github.com/meseta/curatebot/blob/85150e5a39c7adda48e5cdfe43df0a3cebc5c14d/web/src/router/index.ts).

# views/Home.vue
The router file says that when we're at the root of the address, `/` the `Home` component from `views/Home.vue` should be loaded where the <router-view /> is in our `App.vue`. That file in the boilerplate contains the original Vue.js [boilerplate file](https://github.com/meseta/curatebot/blob/0bedad59d2320885fd867da5a9848ae2fd4a88e3/web/src/views/Home.vue), it looks like this:

```vue
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
  name: 'Home',
  components: {
    HelloWorld
  }
}
</script>
```

Again, it tries to load the <HelloWorld> component, which we're deleting. I replace it with this:

```vue
  
<template>
  <v-container>
    <Section>
      <template v-slot:title>Welcome to CurateBot</template>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc faucibus nulla massa, sed porta dui pretium ut. Aenean vulputate laoreet dapibus. Vestibulum lacinia nibh at lectus semper pretium. Pellentesque semper ut ante eget finibus. Ut scelerisque velit neque. Ut porta ex orci, vitae eleifend ante pellentesque in. 
      </p>
    </Section>
  </v-container>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import Section from '@/components/Section.vue'

@Component({ components: { Section } })
export default class HomeView extends Vue {}
</script>
```

I am defining my own <Section> component (which I'll show later), and inside it is a `title` slot for the title of the section, and here I've just added some [Lorem Ipsum](https://www.lipsum.com/)

# components/AppBar.vue
I've moved the app bar component from inside the `App.vue` file to it's own component file, this just keeps things clean and compartmentalized. The file can be seen [here](https://github.com/meseta/curatebot/blob/85150e5a39c7adda48e5cdfe43df0a3cebc5c14d/web/src/components/AppBar.vue), band I'm reproducing it below. It's pretty much an empty component at this point, with just an <v-app-bar> and a placeholder <v-btn> in there.

```vue
<template>
  <v-app-bar app color="primary" dark>
    <v-btn text>Link</v-btn>
  </v-app-bar>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';

@Component
export default class AppBar extends Vue {}
</script>
```

# components/Section.vue
Finally, a new <Section> component that I'm defining. It's based around a <v-card> but with some settings for margins so that the cards are centered on the page (simpler alternative for single-column page layouts than using flex/grid

```vue
<template>
  <v-card
    class="my-4 mx-auto"
    max-width="860"
  >
    <v-card-title class="primary white--text mb-5">
      <slot name="title"></slot>
    </v-card-title>

    <v-card-text>
      <slot></slot>
    </v-card-text>

  </v-card>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component
export default class Section extends Vue {}
</script>
```

A couple of <slot> is defined so that this component can be re-used with different content inserted into it, as seen in `Home.vue`

___
The end result looks like this:

![End result of cleanup](https://dev-to-uploads.s3.amazonaws.com/i/t4xks50ce5616dyyt5x5.png)
 
Very minimal, all the extra junk cleaned up from the boilerplate, ready to receive new content!