In this comprehensive tutorial, we'll build a complete blog using NuxtJS, covering everything from initial setup to deployment.
Prerequisites
Before we begin, make sure you have:
- Node.js (version 14 or higher)
- npm or Yarn package manager
- Basic knowledge of Vue.js and JavaScript
- Text editor (VS Code recommended)
Step 1: Create NuxtJS Application
The easiest way to create a NuxtJS application is by using the create-nuxt-app package. This can be installed by using the command.
yarn create nuxt-app <project-name>
This will run through a few questions to get you setup such as UI Framework, TypeScript, linter, testing framework and even the continuous integration platform you'd like to use.
Once installed you can run your nuxt site by using the following.
cd <project-name>
yarn dev
The application is now running on http://localhost:3000.
To make sure that you can view a page, go to the pages
directory and add a new file for posts.vue
and add a <template></template>
, this will allow you to navigate to http://localhost:3000/posts
to see the new posts page.
Step 2: Install Content Package
Now we have NuxtJS installed and running locally we need to install a package that will allow us to create content for the blog.
NuxtJS has an official package nuxt/content
that will allow you to fetch content inside a markdown file via an API and act as a Git based headless CMS.
To install you can use the following command.
yarn add @nuxt/content
To add modules into NuxtJS you need to add a module into the nuxt.config.js
file.
{
"modules": ["@nuxt/content"],
"content": {
// Options
}
}
Step 3: Create Content Structure
Now we can create a markdown file in the content
folder to fetch and display. As we're creating a blog we might want to have different content types therefore create a articles
folder to place your markdown files inside.
You can define metadata for your blog post by adding a YAML front matter block to the top of the file:
---
title: Your Blog Post Title
slug: your-blog-post-slug
category: web-development
tags: [nuxtjs, vue, javascript]
extension: md
createdAt: 2022-06-12
description: A brief description of your blog post
author: Your Name
---
Your blog post content goes here...
You can then fill out the blog post content using the standard markdown syntax.
Step 4: Create Default Layout
You can extend the main layout in NuxtJS by creating your own default layout, create a file in layouts/default.vue
and it will be used for all your pages that you don't specify a layout.
The simplest layout you can use is by just including in the <nuxt />
tag, this is what nuxt will use to inject in the page component.
<template>
<Nuxt />
</template>
For this blog we want to include a header and footer, we'll use the below file as the main template:
<template>
<div>
<header-bar></header-bar>
<div class="w-full md:container mx-auto px-6">
<Nuxt />
</div>
<footer-bar></footer-bar>
</div>
</template>
Step 5: Create Blog Pages
Homepage (index.vue)
Create an engaging homepage that showcases your latest blog posts:
<template>
<div>
<section class="hero mb-12">
<h1 class="text-4xl font-bold mb-4">Welcome to My Blog</h1>
<p class="text-xl text-gray-600">
Discover articles about web development, Vue.js, and more
</p>
</section>
<section class="latest-posts">
<h2 class="text-2xl font-bold mb-6">Latest Posts</h2>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
<article-card
v-for="post in posts"
:key="post.slug"
:post="post"
/>
</div>
</section>
</div>
</template>
<script>
export default {
async asyncData({ $content }) {
const posts = await $content("articles")
.sortBy("createdAt", "desc")
.limit(6)
.fetch();
return { posts };
},
};
</script>
Blog List Page (blog/index.vue)
<template>
<div>
<h1 class="text-3xl font-bold mb-8">All Blog Posts</h1>
<!-- Search and Filter -->
<div class="mb-8">
<input
v-model="searchTerm"
type="text"
placeholder="Search posts..."
class="w-full p-3 border rounded-lg"
/>
</div>
<!-- Posts Grid -->
<div class="grid md:grid-cols-2 gap-6">
<article-card
v-for="post in filteredPosts"
:key="post.slug"
:post="post"
/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
searchTerm: "",
};
},
async asyncData({ $content }) {
const posts = await $content("articles")
.sortBy("createdAt", "desc")
.fetch();
return { posts };
},
computed: {
filteredPosts() {
if (!this.searchTerm) return this.posts;
return this.posts.filter(
(post) =>
post.title
.toLowerCase()
.includes(this.searchTerm.toLowerCase()) ||
post.description
.toLowerCase()
.includes(this.searchTerm.toLowerCase())
);
},
},
};
</script>
Step 6: SEO Optimization
Add proper meta tags and schema markup for better search engine optimization:
<script>
export default {
head() {
return {
title: this.post.title,
meta: [
{
hid: "description",
name: "description",
content: this.post.description,
},
{
hid: "og:title",
property: "og:title",
content: this.post.title,
},
{
hid: "og:description",
property: "og:description",
content: this.post.description,
},
{ hid: "og:type", property: "og:type", content: "article" },
{
hid: "twitter:card",
name: "twitter:card",
content: "summary_large_image",
},
],
script: [
{
type: "application/ld+json",
json: {
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: this.post.title,
description: this.post.description,
author: {
"@type": "Person",
name: this.post.author,
},
datePublished: this.post.createdAt,
},
},
],
};
},
};
</script>
Step 7: Performance Optimization
Image Optimization
Use the @nuxt/image
module for automatic image optimization:
yarn add @nuxt/image
Add to nuxt.config.js
:
modules: ["@nuxt/content", "@nuxt/image"];
Code Splitting
NuxtJS automatically handles code splitting, but you can optimize further:
// nuxt.config.js
export default {
build: {
optimization: {
splitChunks: {
chunks: "all",
maxSize: 200000,
},
},
},
};
Step 8: Deployment Options
Static Generation with Netlify
- Build your static site:
yarn generate
- Deploy the
dist
folder to Netlify, Vercel, or GitHub Pages.
Server-Side Rendering with Heroku
- Create a
package.json
build script:
{
"scripts": {
"heroku-postbuild": "npm run build"
}
}
- Deploy to Heroku with automatic builds.
Frequently Asked Questions
How do I add a contact form to my NuxtJS blog?
You can add a contact form using the @nuxtjs/axios
module to handle form submissions. Consider using services like Netlify Forms or Formspree for static sites.
Can I use a CMS with my NuxtJS blog?
Yes! You can integrate headless CMS solutions like:
- Contentful
- Strapi
- Ghost
- Forestry
How do I improve my blog's loading speed?
- Enable gzip compression
- Use the
@nuxt/image
module for image optimization - Implement lazy loading for images
- Use a CDN for static assets
- Enable browser caching
How do I add analytics to my NuxtJS blog?
Install the @nuxtjs/google-analytics
module:
yarn add @nuxtjs/google-analytics
See our guide on adding Google Analytics to Nuxt3 for detailed instructions.
Can I add a dark mode to my blog?
Yes! Use the @nuxtjs/color-mode
module for easy dark mode implementation with automatic system preference detection.
Related NuxtJS Resources
Enhance your NuxtJS blog with these additional features:
- Add cache control to Nuxt3 for better performance
- CSS media queries for responsive design
- CSS responsive tables for data presentation
Best Practices
- Content Organization: Use a clear folder structure for your content
- Image Optimization: Always compress and resize images appropriately
- SEO: Include proper meta tags and schema markup
- Performance: Regularly audit your site with Lighthouse
- Accessibility: Use semantic HTML and proper ARIA labels
Conclusion
You now have a complete, production-ready blog built with NuxtJS. This setup provides excellent performance, SEO capabilities, and developer experience. The modular architecture makes it easy to extend with additional features as your blog grows.
Remember to regularly update your dependencies and consider implementing a CI/CD pipeline for automated deployments.