Best Practices for Nuxt.js SEO

One of the biggest selling points of Nuxt.js is that it can help your application with Search Engine Optimization (SEO) and to rank better on Google. In this article, we’ll go over the best practices to make sure that your Nuxt application is set up properly to rank on search engines.

Disclaimer: This article is not an SEO guide or a guide on how to rank well on Google. It’s a technical article on how to best set up meta tags and redirects in your Nuxt application, which helps with SEO.

How Nuxt.js helps you with SEO

Before we dive in, let’s quickly go over what Nuxt is and how it can help you put together your application for SEO purposes.

Single Page Applications aren’t set up for SEO

Usually with Vue.js, you’re creating a single page application. That’s a purely JavaScript-generated application where there’s only one file, a blank index.html. The content is populated into index.html after the JavaScript has initially loaded, and JavaScript also takes care of switching routes.

SPAs are great for creating snappy UIs, but when it comes to SEO, single page applications are not ideal because they have no initial content. That makes it difficult for Google and other crawlers (including social media crawlers like Facebook) to crawl your website and to display it properly in the search results.

Nuxt.js makes it simple to create a universal application

A universal application is about preloading your application on a web server and sending rendered HTML as the response to the browser for every route in your app in order to improve SEO, make loading happen faster, along with many other benefits.

With a universal application, there will be content on the page like <title> tags and <meta> tags in the <head> and <h1> tags in the <body>before any JavaScript has loaded. Those tags help crawlers determine what’s on the page.

How Nuxt.js handles the head for all your pages

Nuxt uses a library called vue-meta to handle the <head> element in each of your pages. A page is just Nuxt’s term for a route, and each one lives inside of a pages folder.

Nuxt gives you three ways to set up the <head> element within your application’s pages. Let’s review them now.

1) Setting up default meta tags for all pages

It’s not uncommon for different pages throughout your application to share some of the same meta tags. Nuxt lets you set up the defaults for each of your pages by setting up the head property in the nuxt.config.jsfile.

module.exports = {
head: {
titleTemplate: '%s - Nuxt.js',
meta: [ // Each object in this array is its own meta tag
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial scale=1' },
{ hid: 'description', name: 'description', content: 'Meta description' }

Click here to see all of the properties that you can define inside of the head property.

Note: Nuxt.js uses head for the name of the property. vue-meta uses metaInfo. It’s the same property.

2) Setting up meta tags for your pages individually

Inside of each of your Nuxt pages, you can define a head method. You can manually customize the head tags for an individual page and Nuxt will overwrite whatever you set as the default in the nuxt.config.jsfile.

Here’s an example About.vue file with its own meta tags in the head method:

<h1>About Page</h1>
export default {
head () {
return {
title: 'About Us - Nuxt.js',
meta: [
{ hid: 'description', name: 'description', content: 'About our company Nuxt.js ' }

3) Setting up meta tags for your dynamic pages

You can further customize your meta tags with dynamic pages — pages where there’s one route that can be rendered differently. A user profile page might be one example.

Dynamic routes are defined by prefixing your .vue component or directory in the pages folder with an underscore.

--| users/
-----| _username.vue

This will generate your Vue.js route code like the following:

router: {
routes: [{
name: 'users-id',
path: '/users/:username?',
component: 'pages/users/_username.vue'

And inside of the head method, you’d have access to your component data with this. You can use the data you have access to inside of the this property to customize how your meta tags are rendered with the data of your component.

Here’s an example of how the meta tags for that user profile page could be rendered:

head () {
let user = this.user;

return {
title: `${user.fullName} @(${user.userName}) - Nuxt.js`,
meta: [{
hid: `iOSUrl`,
property: 'al:ios:url',
content: `myapp://user?screen_name=${user.userName}`
hid: `description`,
name: 'description',
content: `${user.fullName}'s public profile at Nuxt.js`

What is hid and how does it help SEO?

You might have noticed the hid property in the meta tag examples from above. That’s a property that’s being used to help mitigate default vue-meta behavior.

By default, when using vue-meta, it will create duplicate tags instead of replacing the original tag. But Google can penalize you for having duplicate tags when it crawls your website, so it’s best to always have a unique hid property on each of your meta tags to uniquely identify them. Having the hid property will signal to vue-meta to replace the tag instead of duplicating it.

Click here to learn more about duplicated meta tags and how hid can help you avoid them.

Handling redirects with Nuxt.js

According to HubSpot, a 301 redirect is a permanent redirect from one URL to another. 301 redirects send site visitors and search engines to a different URL than the one they originally typed into their browser or selected from a search-engine results page.

301 redirects are common to use when the structure of your website changes and you still want to maintain the ranking power of the original link.

Nuxt helps you with this case by setting you up with a serverMiddleware property inside of your nuxt.config.js file. The serverMiddleware property helps you to set up middleware that will run when the page is rendered on the server-side.

Here’s an example of using this property to set up a function that handles 301 redirects for your application.

module.exports = {
serverMiddleware: [

You can define the routes that need to be redirected inside of the file called /301.json and import it into seo.js middleware.

{ "from": "/old", "to": "/new" },
{ "from": "/veryold", "to": "/verynew" },
{ "from": "/too-old", "to": "/new" }

Then you can have the file run through the routes that you defined in 301.json and have it return a 301 response for each one, along with the appropriate HTTP Headers.

const redirects = require('../301.json');
module.exports = function (req, res, next) {

const redirect = redirects.find(r => r.from === req.url);
  if (redirect) {
console.log(`redirect: ${redirect.from} => ${}`);
res.writeHead(301, { Location: });
} else {

Click here to learn more about Nuxt.js middleware and how it can help you with more than just redirects.

SEO effects when rendering your app in spa mode

There are more than one build mode in Nuxt apps. You can choose to render your application as universal, or spa.

What are the effects of managing all of the tags in the <head> if you choose to render your application in spa mode?

Since server-side rendering is not taking place, you won’t get any of the benefits of having content initially on your page. vue-meta still does its job of handling the <head>, but if you’re rendering your application as a single page application, there’s no content on the page initially because all the tags would be created after the JavaScript has loaded. The only effects are purely front-end. For example, updating the title tag when the user has changed views.


Nuxt gives you a lot of control over how you render the <head> element in your universal application, which helps with SEO. You have many options for setting global defaults inside of the nuxt.config.js file and you also have access to a head method in each individual page where you can further customize things. Lastly, you can set up a serverMiddleware that can take care of things like 301 redirects to maintain a link’s ranking power. will be creating content on Nuxt applications in the following months, create a free account today and get notified when it’s released.

Keep Reading