skip to content

Building a SEO Friendly Blog: Getting Started with Nuxt

2020-09-18

Static Site

Throughout my career, I have worked with several firms that specialize in Search Engine Optimization. After you've worked with a few, you realize that much of SEO is a moving target, with no one being quite sure what is the best practice on all fronts. Company A will focus on each product page or post's paths, and when you switch to Company B, they'll have you change the routes that you just set due to the previous company's suggestion.

How search engines index websites will always be in flux, but there are specific strategies that you can employ to get higher rankings and ensure those that would be interested in your content are more likely to find it.

While we know that web crawlers will now execute a page's JavaScript, what is unclear how long the robot will wait for your content to finish loading. What we do know is that sites that load faster tend to perform better, meaning not having to wait for an expensive API call to render the main content will boost your site's performance. While you may decide to use AJAX to retrieve comments on your post to ensure you display the latest content, there is typically no reason the blog post itself cannot be rendered server-side or delivered as static content.

Using a framework like Nuxt makes creating a statically generated site straight forward. For this tutorial, you will need to have Node version 8.9.0 or later installed to follow along. This tutorial does assume you understand the basics of working with npm. If you are unfamiliar with npm, I recommend reading this article from Nodesource: An Absolute Beginner's Guide to Using npm.

In the directory where you're going to build your project, first, create a package.json file using the command npm init. This command will start a wizard in your terminal that will let you specify your project's base configuration. After going through the wizard, you will have a file that looks similar to this:

{
  "name": "sample-blog",
  "version": "1.0.0",
  "description": "A sample blog using Nuxt",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jessie Barnett",
  "license": "MIT",
  "dependencies": {
    "nuxt": "^2.14.5"
  }
}

The next step is to install Nuxt by running the command npm install nuxt. This command will add it to your package.json and create a package-lock.json file. With Nuxt installed, we need to add two scripts to the package.json file to support running the application in development mode and generating a static site.

{
  "name": "sample-blog",
  "version": "1.0.0",
  "description": "A sample blog using Nuxt",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nuxt",
    "generate": "nuxt generate"
  },
  "author": "Jessie Barnett",
  "license": "MIT",
  "dependencies": {
    "nuxt": "^2.14.5"
  }
}

Nuxt is an opinionated framework that utilizes pre-determined directory structures to figure out how to stitch together your website. To create a page for your website, you will need to create a pages directory using mkdir pages. Inside of this directory, you will need to create an index.vue file, which will be the page served up by going to your website's / route.

We'll create a basic template for our landing page for now. Update your index.vue file to have the following code:

<template>
  <p>Landing Page</p>
</template>

If you run the command npm run dev and navigate to http://localhost:3000 you can see your rendered template. Now let's add a dynamic route for our blog posts. We will be creating a slug, which is noted by the filename starting with an underscore. Let's make a blog directory in the pages directory and add a _slug.vue file to it.

To see the dynamic page in action, we will use the asyncData hook provided by Nuxt. This hook takes in a context object, which has quite a few useful attributes, but we will focus on the route. We can get the path parameter from context.route.params.slug, where slug represents what we called the file. If we had called the file _post.vue instead, we'd need to address it via context.route.params.post. Our hook will need to return an object with this parameter to render it in the template.

Update your _slug.vue file to have the following code:

<template>
  <p>{{ blogPost }}</p>
</template>

<script>
export default {
  asyncData ({route}) {
    return {
      blogPost: route.params.slug
    }
  }
}
</script>

Assuming your dev server is still running, if you navigate to http://localhost:3000/blog/my-post you should see that the page prints out the URI's dynamic parameter.

The last thing we need to address is static site generation. Nuxt uses a crawler to determine what dynamic routes to generate, meaning we either need to manually config Nuxt to know about all of our routes or add links to them. For today, we will go with adding links.

Open up your index.vue file and update it to have the following code:

<template>
  <div>
    <h1>Articles</h1>
    <ul>
      <li>
        <nuxt-link to="/blog/cats">Article on Cats</nuxt-link>
      </li>
      <li>
        <nuxt-link to="/blog/dogs">Article on Dogs</nuxt-link>
      </li>
      <li>
        <nuxt-link to="/blog/parrots">Article on Parrots</nuxt-link>
      </li>
    </ul>
  </div>
</template>

You're now ready to generate a static site using the command npm run generate. The output of this command will be a dist folder, in which you should see an index.html for your landing page and all three "blog posts" we linked to from the landing page.

That's it for this part of the series! In the next part we'll discuss how you can use a combination of Markdown, Frontmatter, and a context loader to import articles and create an article list.