- Understanding Nuxt.js
- Creating Pages and Layouts
- Fetching Data from an API
- Using Vuex for State Management
- Configuring Plugins in Nuxt.js
- Advanced Nuxt.js Features
- Deploying Your Nuxt.js Application
- SEO and Performance Optimization
- Testing Nuxt.js Applications
- Integrating GraphQL with Nuxt.js
- Creating a Blog with Nuxt.js Content
- Conclusion
Nuxt.js is a powerful framework built on top of Vue.js that makes it easier to create server-side rendered (SSR) applications. SSR offers many benefits, including improved performance, better SEO, and enhanced user experience. In this guide, we’ll explore how to build server-side rendered apps using Nuxt.js, from setting up your development environment to deploying your application.
Understanding Nuxt.js

Nuxt.js simplifies the development of SSR applications by providing a robust structure and a set of useful features. It handles the configuration of Vue.js, Vue Router, and Vuex, offering a seamless development experience.
With Nuxt.js, you can also choose between SSR, static site generation (SSG), and single-page applications (SPA), making it a versatile tool for various types of projects.
Setting Up Your Nuxt.js Project
To get started with Nuxt.js, you need to set up your development environment. First, ensure that you have Node.js and npm installed on your machine. You can download the latest version of Node.js from the official website, which also includes npm.
Once Node.js and npm are installed, you can create a new Nuxt.js project using the Create Nuxt App command:
npx create-nuxt-app my-nuxt-app
cd my-nuxt-app
The command will prompt you to answer a few questions to configure your project, such as the project name, programming language (JavaScript or TypeScript), and additional modules to include.
Running the Development Server
After setting up your project, navigate to the project directory and start the development server:
npm run dev
Your Nuxt.js application is now running on http://localhost:3000
, and you can start building your server-side rendered app.
Creating Pages and Layouts
Nuxt.js uses a file-based routing system, where each file in the pages
directory corresponds to a route in your application. For example, creating a file named about.vue
in the pages
directory will create a route at /about
.
Adding a Home Page
To add a home page, create an index.vue
file in the pages
directory:
<template>
<div>
<h1>Welcome to My Nuxt.js App</h1>
<p>This is the home page.</p>
</div>
</template>
<script>
export default {
name: 'HomePage',
};
</script>
This template defines the content and structure of the home page, and the <script>
section exports the component.
Creating a Layout
Layouts in Nuxt.js allow you to define a common structure for your pages, such as a header and footer. To create a layout, add a default.vue
file in the layouts
directory:
<template>
<div>
<header>
<nav>
<nuxt-link to="/">Home</nuxt-link>
<nuxt-link to="/about">About</nuxt-link>
</nav>
</header>
<nuxt />
<footer>
<p>© 2023 My Nuxt.js App</p>
</footer>
</div>
</template>
<script>
export default {
name: 'DefaultLayout',
};
</script>
<style>
header {
background: #333;
color: white;
padding: 1rem;
}
footer {
background: #333;
color: white;
padding: 1rem;
text-align: center;
}
</style>
The <nuxt />
component in the layout file is a placeholder for the content of your pages. This layout will be applied to all pages by default.
Adding an About Page
To add an about page, create an about.vue
file in the pages
directory:
<template>
<div>
<h1>About Us</h1>
<p>This is the about page.</p>
</div>
</template>
<script>
export default {
name: 'AboutPage',
};
</script>
Now you have a basic Nuxt.js application with a home page, an about page, and a default layout.
Fetching Data from an API
One of the main benefits of server-side rendering is the ability to fetch data before rendering the page. Nuxt.js provides a fetch
method that you can use to fetch data asynchronously.
Using the Fetch Method
To fetch data for the about page, modify the about.vue
file to use the fetch
method:
<template>
<div>
<h1>About Us</h1>
<p>This is the about page.</p>
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'AboutPage',
data() {
return {
users: [],
};
},
async fetch() {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
this.users = await response.json();
},
};
</script>
In this example, the fetch
method retrieves data from an API and assigns it to the users
data property. The data is then rendered in the template.
Using Vuex for State Management

Vuex is the state management library for Vue.js applications, and it integrates seamlessly with Nuxt.js. Vuex helps manage the application’s state in a centralized store, making it easier to manage and debug.
Setting Up Vuex in Nuxt.js
Nuxt.js automatically recognizes Vuex stores. To set up Vuex, create a store
directory in your project root. Inside this directory, create an index.js
file:
// store/index.js
export const state = () => ({
users: [],
});
export const mutations = {
SET_USERS(state, users) {
state.users = users;
},
};
export const actions = {
async fetchUsers({ commit }) {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
commit('SET_USERS', users);
},
};
This example sets up a Vuex store with state, mutations, and actions. The fetchUsers
action fetches data from an API and commits a mutation to update the state.
Using Vuex in Components
With Vuex set up, you can now use it in your components. Modify the about.vue
file to use Vuex for state management:
<template>
<div>
<h1>About Us</h1>
<p>This is the about page.</p>
<ul>
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'AboutPage',
async fetch({ store }) {
await store.dispatch('fetchUsers');
},
computed: {
users() {
return this.$store.state.users;
},
},
};
</script>
In this example, the fetch
method dispatches the fetchUsers
action, and the component uses a computed property to access the users
state from the Vuex store.
Configuring Plugins in Nuxt.js

Plugins in Nuxt.js allow you to add external libraries and functionality to your application. You can configure plugins to be available globally or for specific parts of your application.
Adding a Plugin
To add a plugin, create a plugins
directory in your project root. Inside this directory, create a JavaScript file for your plugin. For example, to add Axios for making HTTP requests, create an axios.js
file:
// plugins/axios.js
import axios from 'axios';
export default ({ app }, inject) => {
const instance = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
});
inject('axios', instance);
};
Next, register the plugin in the nuxt.config.js
file:
// nuxt.config.js
export default {
plugins: ['~/plugins/axios.js'],
};
Now, you can use Axios in your components and pages:
<template>
<div>
<h1>Data from API</h1>
<ul>
<li v-for="post in posts" :key="post.id">{{ post.title }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'DataPage',
data() {
return {
posts: [],
};
},
async mounted() {
const response = await this.$axios.get('/posts');
this.posts = response.data;
},
};
</script>
In this example, Axios is used to fetch data from an API when the component is mounted.
Advanced Nuxt.js Features
Nuxt.js provides several advanced features that can enhance your application’s performance and capabilities. Let’s explore some of these features.
Middleware

Middleware in Nuxt.js allows you to run custom code before rendering a page. This is useful for tasks like authentication and setting headers.
To create middleware, add a middleware
directory in your project root. Inside this directory, create a JavaScript file for your middleware. For example, to create an authentication middleware, add an auth.js
file:
// middleware/auth.js
export default function ({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login');
}
}
Next, apply the middleware to a page or globally in the nuxt.config.js
file:
// pages/profile.vue
<template>
<div>
<h1>Profile Page</h1>
<p>Welcome to your profile.</p>
</div>
</template>
<script>
export default {
middleware: 'auth',
};
</script>
In this example, the auth
middleware checks if the user is authenticated and redirects to the login page if not.
Modules

Nuxt.js modules are reusable packages that extend the functionality of your application. They can include plugins, middleware, and more. You can find a variety of modules for different purposes, such as authentication, PWA support, and analytics.
To install a module, use npm or yarn. For example, to add the @nuxtjs/auth-next
module for authentication, run:
npm install @nuxtjs/auth-next
Then, configure the module in the nuxt.config.js
file:
// nuxt.config.js
export default {
modules: [
'@nuxtjs/axios',
'@nuxtjs/auth-next',
],
auth: {
strategies: {
local: {
token: {
property: 'token',
global: true,
// required: true,
// type: 'Bearer'
},
user: {
property: 'user',
// autoFetch: true
},
endpoints: {
login: { url: '/api/auth/login', method: 'post' },
logout: { url: '/api/auth/logout', method: 'post' },
user: { url: '/api/auth/user', method: 'get' }
}
}
}
}
};
With this configuration, you can handle authentication in your Nuxt.js application using the provided endpoints and strategies.
Deploying Your Nuxt.js Application
Deploying a Nuxt.js application involves building your project for production and deploying it to a server. Nuxt.js supports various deployment targets, including static site hosting, serverless platforms, and traditional servers.
Building for Production
To build your Nuxt.js application for production, run the following command:
npm run build
This command generates the necessary files in the dist
directory for deployment.
Deploying to Vercel
Vercel is a popular platform for deploying Nuxt.js applications. To deploy your application to Vercel, follow these steps:
- Install the Vercel CLI:
npm install -g vercel
- Log in to your Vercel account:
vercel login
- Deploy your application:
vercel
The Vercel CLI will guide you through the deployment process, and your Nuxt.js application will be live on the internet in minutes.
Deploying to Netlify
Netlify is another popular platform for deploying Nuxt.js applications. To deploy your application to Netlify, follow these steps:
- Install the Netlify CLI:
npm install -g netlify-cli
- Log in to your Netlify account:
netlify login
- Create a
netlify.toml
file in your project root:
[build]
command = "npm run build"
publish = "dist"
- Deploy your application:
netlify deploy --prod
The Netlify CLI will guide you through the deployment process, and your Nuxt.js application will be live on Netlify.
Deploying to Traditional Servers
If you prefer deploying to traditional servers, you can build your Nuxt.js application and serve it using a Node.js server. Create a server.js
file in your project root:
// server.js
const { Nuxt, Builder } = require('nuxt');
const express = require('express');
const app = express();
const config = require('./nuxt.config.js');
config.dev = process.env.NODE_ENV !== 'production';
const nuxt = new Nuxt(config);
if (config.dev) {
new Builder(nuxt).build();
}
app.use(nuxt.render);
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server listening on http://localhost:${port}`);
});
Start the server using the following command:
node server.js
You can deploy this setup to any hosting provider that supports Node.js, such as DigitalOcean, AWS, or Heroku.
SEO and Performance Optimization
Optimizing your Nuxt.js application for SEO and performance is crucial for improving user experience and search engine rankings. Nuxt.js provides various tools and best practices to help you achieve this.
Meta Tags and Open Graph
Adding meta tags and Open Graph tags to your pages can improve your SEO and the appearance of your pages when shared on social media. Nuxt.js makes it easy to add these tags using the head
property in your page components.
For example, to add meta tags to the home page, modify the index.vue
file:
<template>
<div>
<h1>Welcome to My Nuxt.js App</h1>
<p>This is the home page.</p>
</div>
</template>
<script>
export default {
name: 'HomePage',
head() {
return {
title: 'Home - My Nuxt.js App',
meta: [
{ hid: 'description', name: 'description', content: 'Welcome to my Nuxt.js application' },
{ property: 'og:title', content: 'Home - My Nuxt.js App' },
{ property: 'og:description', content: 'Welcome to my Nuxt.js application' },
],
};
},
};
</script>
Lazy Loading and Code Splitting

Nuxt.js automatically splits your JavaScript bundles to improve load times. However, you can further enhance performance by lazy loading components that are not immediately needed.
For example, to lazy load a component, use the dynamic import syntax in your pages/index.vue
file:
<template>
<div>
<h1>Welcome to My Nuxt.js App</h1>
<button @click="loadComponent">Load Component</button>
<DynamicComponent v-if="componentLoaded" />
</div>
</template>
<script>
export default {
name: 'HomePage',
data() {
return {
componentLoaded: false,
};
},
methods: {
loadComponent() {
import('../components/DynamicComponent.vue').then((module) => {
this.$options.components.DynamicComponent = module.default;
this.componentLoaded = true;
});
},
},
};
</script>
Image Optimization
Images can significantly impact the load time of your web pages. Nuxt.js provides an @nuxt/image
module that automatically optimizes images for you. To use this module, install it and configure it in your nuxt.config.js
file:
npm install @nuxt/image
// nuxt.config.js
export default {
modules: ['@nuxt/image'],
image: {
// Options
},
};
You can then use the <nuxt-img>
component to optimize and display images:
<template>
<div>
<h1>Welcome to My Nuxt.js App</h1>
<nuxt-img src="/images/my-image.jpg" alt="My Image" width="500" height="500" />
</div>
</template>
Caching and CDN
Using a Content Delivery Network (CDN) and caching static assets can significantly improve the performance of your application. Nuxt.js allows you to configure caching headers to leverage browser caching.
To set up caching, add the following configuration to your nuxt.config.js
file:
// nuxt.config.js
export default {
render: {
static: {
maxAge: '1y', // Cache static assets for one year
},
},
};
Additionally, you can use a CDN to serve your static assets. Services like Cloudflare, Amazon CloudFront, and Netlify offer CDN capabilities that can be easily integrated with Nuxt.js.
Monitoring and Analytics
Monitoring the performance of your Nuxt.js application and understanding user behavior are crucial for continuous improvement. Tools like Google Analytics, Sentry, and New Relic can provide valuable insights.
To integrate Google Analytics, you can use the @nuxtjs/google-analytics
module. Install the module and configure it in your nuxt.config.js
file:
npm install @nuxtjs/google-analytics
// nuxt.config.js
export default {
modules: ['@nuxtjs/google-analytics'],
googleAnalytics: {
id: 'UA-XXXXXXXXX-X', // Replace with your Google Analytics tracking ID
},
};
Testing Nuxt.js Applications
Testing is an essential part of the development process. Nuxt.js supports various testing frameworks and tools to ensure the quality and reliability of your application.
Unit Testing with Jest
Jest is a popular testing framework that can be used to test your Nuxt.js components and Vuex store. To set up Jest in your Nuxt.js project, install the necessary dependencies:
npm install --save-dev jest @vue/test-utils babel-jest vue-jest
Create a jest.config.js
file in your project root:
module.exports = {
moduleFileExtensions: ['js', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'^.+\\.js$': 'babel-jest',
},
testEnvironment: 'jsdom',
};
Write a simple test for a component, for example, components/HelloWorld.vue
:
<template>
<div>
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
props: {
msg: String,
},
};
</script>
Create a test file components/HelloWorld.spec.js
:
import { shallowMount } from '@vue/test-utils';
import HelloWorld from './HelloWorld.vue';
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'Hello, Nuxt.js!';
const wrapper = shallowMount(HelloWorld, {
propsData: { msg },
});
expect(wrapper.text()).toMatch(msg);
});
});
Run the tests using the following command:
npm run test
End-to-End Testing with Cypress
Cypress is a powerful tool for end-to-end testing, allowing you to test your Nuxt.js application in a real browser environment. To set up Cypress, install it using npm:
npm install --save-dev cypress
Create a cypress.json
file in your project root with the following configuration:
{
"baseUrl": "http://localhost:3000"
}
Write a simple end-to-end test in cypress/integration/sample_spec.js
:
describe('My First Test', () => {
it('Visits the app root url', () => {
cy.visit('/');
cy.contains('h1', 'Welcome to My Nuxt.js App');
});
});
Run Cypress using the following command:
npx cypress open
This command opens the Cypress test runner, where you can run your end-to-end tests.
Integrating GraphQL with Nuxt.js

GraphQL is a powerful query language for APIs that allows you to request only the data you need. Integrating GraphQL with Nuxt.js can enhance your application’s data-fetching capabilities.
Setting Up GraphQL
To get started with GraphQL, you need to install the @nuxtjs/apollo
module:
npm install @nuxtjs/apollo
Configure the module in your nuxt.config.js
file:
// nuxt.config.js
export default {
modules: ['@nuxtjs/apollo'],
apollo: {
clientConfigs: {
default: {
httpEndpoint: 'https://api.spacex.land/graphql/',
},
},
},
};
Using GraphQL in Components
With the Apollo module set up, you can now use GraphQL queries in your components. Create a component that fetches data from a GraphQL API:
<template>
<div>
<h1>SpaceX Launches</h1>
<ul>
<li v-for="launch in launches" :key="launch.id">{{ launch.mission_name }}</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag';
export default {
data() {
return {
launches: [],
};
},
apollo: {
launches: {
query: gql`
query {
launchesPast(limit: 5) {
id
mission_name
}
}
`,
},
},
};
</script>
In this example, the Apollo module fetches data from the SpaceX GraphQL API and binds it to the launches
data property.
Creating a Blog with Nuxt.js Content

Nuxt.js Content is a powerful module for managing content in your Nuxt.js application. It allows you to write content in Markdown or JSON and use it as a data source for your application.
Setting Up Nuxt.js Content
To get started with Nuxt.js Content, install the module:
npm install @nuxt/content
Configure the module in your nuxt.config.js
file:
// nuxt.config.js
export default {
modules: ['@nuxt/content'],
content: {
// Options
},
};
Adding Content
Create a content
directory in your project root and add a Markdown file, for example, content/hello.md
:
---
title: Hello World
description: Welcome to my blog
---
# Hello World
This is my first blog post.
Displaying Content
To display the content in your application, create a page that uses the Nuxt.js Content module:
<template>
<div>
<h1>{{ article.title }}</h1>
<nuxt-content :document="article" />
</div>
</template>
<script>
export default {
async asyncData({ $content, params }) {
const article = await $content(params.slug).fetch();
return { article };
},
};
</script>
This example fetches the content from the content
directory and renders it using the <nuxt-content>
component.
Conclusion
Building server-side rendered applications with Nuxt.js offers numerous benefits, including improved performance, SEO, and user experience. Nuxt.js simplifies the development process by providing a robust framework with powerful features like Vuex for state management, middleware, plugins, and modules like Nuxt.js Content and Apollo for enhanced functionality.
By following the steps outlined in this guide, you can create, configure, and deploy a server-side rendered application using Nuxt.js. Whether you are a beginner or an experienced developer, Nuxt.js provides the tools and flexibility needed to build modern web applications.
Read Next: