Skip to main content

Migrating to Nuxt.js.

Switching tech stack once again. This time from Next to Nuxt.

I've previously written about my migrations before. Though only in so far as what was changing, never why, or how or anything in-depth.

This time I want to make some deeper and more meaningful notes about the migration: Why | How | What

Why?

At work, I am a Vue developer. I work with Vue, and I like Vue. We also use Nuxt on top of Vue. I Love Nuxt. it's nice to use, nice to write, nice to test. And nice to deploy. Nice!

This website was previously written in React with Next.js. I must admit I never liked the React syntax. JSX is not for me. I am a developer who likes to write HTML. I like the syntax. I like to add CSS and Javascript on top of that. I most certainly do not like to write HTML in JavaScript.

So I use Nuxt a lot. And Nuxt has a cool content module which is perfect for building a personal website with a blog. With this module, it becomes very easy to combe markdown content with a Vue website.

I also like the fact that it lets you use Vue components directly inside the markdown files.

I am writing this post mid-migration. Not only am I changing folder structure but also updating the way the site works. I want to use it as more of a blog rather than just showing images of previous work and writing a little about it.

Rather, I want to showcase some work, but also take aspects of those projects and write about them in their own light. I want to dissect them and explain the origin, the problem and the solution.

I will be moving from labelling everything as a post to having some sections for displaying work but moving a lot of content under the blog section.

My site was previously written using TailwindCSS which as a Developer feels wrong, but as someone who is paid to build sites just makes life so much easier. That maybe is worth a separate post on its own, but I must say, after separation of concerns being the separation of filetypes, and feeling like my CSS should describe my content, using utility classes lets me iterate faster, fix bugs quicker, and most importantly ship sites faster.

So this site will now use Nuxt + Tailwind JIT.

module.exports = {
  mode: "jit",
  ...
}

Folder Structure

Content

I was unhappy to hear that I cannot combine my data (eg markdown files) in the same folders as my assets (images, videos)

My original plan was to follow a structure

+-- /content/blog/
| +-- first-post/
| +-- index.md
| +-- img/
| +-- index.jpg

But instantly I ran into problems. /content is not deployed by anything. The content module just reads the markdown files.

I needed to move the files somewhere. static was the recommended location as this does not need to be processed by Webpack so would not change often.

As I was migrating this nuxt/image was released and I quickly moved to this plugin for my images.

There were still a few minor things to iron out with this structure though:

+-- /content/blog/
| +-- first-post.md
| +-- second-post.md
| +-- third-post.md
+-- /static/images/blog/
| +-- first-post/
| | +-- index.jpg
| +-- second-post/
| | +-- index.jpg
| +-- third-post/
| | +-- index.jpg

Now my images and other assets or not in the same directory.

component code for markdown-image, and component code for ui-image.

Component I call <markdown-image/>.

<template>
  <div class="">
    <nuxt-img :src="`/images${this.$route.path}/${this.src}`" :alt="alt" />
  </div>
</template>

<script>
  export default {
    props: {
      src: {
        type: String,
        required: true,
        default: () => "index.jpg",
      },
      alt: {
        type: String,
        required: false,
        default: () => "",
      },
    },
  };
</script>

This one I only use in the markdown. Note I am using the nuxt/image module which is great. This one will read the current route path and find the folder inside /static/images/ and then look for the image src which is passed in as a prop. The image also accepts a prop for the alt text, which can be blank if necessary for presentation images only.

This can then be used inside the markdown file as:

## Content

<markdown-image src="speaker-library-small.jpg" alt="speaker library showing card layout with each speakers image, name, social media link and description text."/></markdown-image>

Components

For my components, I have toyed with many different structures in the past.

I like nesting folders and having my components neatly arranged.

For example, my home page has a blog section listing the latest 3 posts, which contains a card which details the post information.

I have this set up in a structure

+-- /components/
| +-- blog/
| +-- Card.vue
| +-- Promo.vue
| +-- work/
| +-- Card.vue
| +-- Promo.vue

Other elements used often I like to group under the folder name ui. Then where I need to use them I can simply call UiButton or ui-button whichever your flavour.

+-- /ui/
| +-- Modal.vue
| +-- Button.vue
| +-- Card.vue

Similar to how Vue recommends using The for unique components - I hate the terminology and replace instead with site so:

+-- /site/
| +-- Header.vue
| +-- Footer.vue
| +-- Logo.vue
| +-- Notifications.vue

In some of my work projects I like to use a similar structure, grouping components that are related to agenda, or speakers or items that are related neatly together:

+-- /components/
| +-- agenda/
| +-- Item.vue
| +-- Entry.vue
| +-- EntryCompact.vue
| +-- Utility.vue