Building a Modern Blog with Nuxt 3
Create a beautiful, performant, and SEO-friendly blog using Nuxt 3, TailwindCSS, and modern web development practices.
Table of Contents
1 Project Setup and Configuration
Setting up a new Nuxt 3 project with essential dependencies
Lets start by creating a new Nuxt 3 project and configuring it with the necessary dependencies for building a modern blog.
npx nuxi init modern-blog
cd modern-blog
# Install dependencies
npm install @nuxtjs/tailwindcss @nuxtjs/color-mode
npm install @tailwindcss/typography
# Configure nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@nuxtjs/color-mode'
],
colorMode: {
classSuffix: ''
}
})
Pro Tip
2 Content Management with Nuxt Content
Implementing a Git-based content management system
Nuxt Content v2 provides a powerful Git-based CMS that allows you to write your blog posts in Markdown with front matter.
# Install Nuxt Content
npm install @nuxt/content
# Create your first blog post
# content/blog/hello-world.md
---
title: Hello World
description: My first blog post
date: 2024-03-10
---
# Hello World
Welcome to my blog!
Pro Tip
3 Dynamic Routes and Pagination
Creating dynamic blog post routes with pagination
Set up dynamic routing for blog posts and implement pagination for the blog listing page.
// pages/blog/[...slug].vue
const { data: post } = await useAsyncData('post',
() => queryContent('blog')
.where({ slug: route.params.slug })
.findOne()
)
// pages/blog/page/[page].vue
const page = computed(() => parseInt(route.params.page as string) || 1)
const { data: posts } = await useAsyncData('posts',
() => queryContent('blog')
.sort({ date: -1 })
.skip((page.value - 1) * 10)
.limit(10)
.find()
)
Pro Tip
4 SEO and Meta Tags
Optimizing your blog for search engines
Implement proper SEO meta tags and social sharing cards for your blog posts.
// composables/useBlogMeta.ts
export const useBlogMeta = (post) => {
useHead({
title: post.title,
meta: [
{ name: 'description', content: post.description },
{ property: 'og:title', content: post.title },
{ property: 'og:description', content: post.description },
{ property: 'og:image', content: post.image },
{ name: 'twitter:card', content: 'summary_large_image' }
]
})
}
Pro Tip
5 Search and Categories
Adding search functionality and category filtering
Implement client-side search and category filtering for your blog posts.
// composables/useSearch.ts
export const useSearch = () => {
const searchQuery = ref('')
const selectedCategory = ref('all')
const filteredPosts = computed(() => {
let results = posts.value
if (searchQuery.value) {
results = results.filter(post =>
post.title.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
post.description.toLowerCase().includes(searchQuery.value.toLowerCase())
)
}
if (selectedCategory.value !== 'all') {
results = results.filter(post =>
post.category === selectedCategory.value
)
}
return results
})
return {
searchQuery,
selectedCategory,
filteredPosts
}
}
Pro Tip
6 Syntax Highlighting and MDX
Adding code syntax highlighting and MDX support
Enhance your blog posts with syntax highlighting for code blocks and MDX for interactive components.
// Install required packages
npm install @nuxt/content @nuxtjs/color-mode shiki
// nuxt.config.ts
export default defineNuxtConfig({
content: {
highlight: {
theme: {
default: 'github-light',
dark: 'github-dark'
}
}
}
})
Pro Tip
7 Add Comments Section
Enable user engagement with a comments section.
Implement a comment system and social sharing buttons for your blog posts.
// components/Comments.vue
<script setup>
const { data: comments } = await useAsyncData('comments',
() => $fetch('/api/comments/' + props.postId)
)
const addComment = async (content) => {
await $fetch('/api/comments/' + props.postId, {
method: 'POST',
body: { content }
})
// Refresh comments
await refresh()
}
<script>
Pro Tip
8 RSS Feed and Sitemap
Generating RSS feed and sitemap
Add RSS feed and sitemap generation for better discoverability.
// nuxt.config.ts
import { SitemapStream, streamToPromise } from 'sitemap'
import { Readable } from 'stream'
export default defineNuxtConfig({
hooks: {
'build:done': async () => {
const posts = await queryContent('blog').find()
const stream = new SitemapStream({ hostname: 'https://yourblog.com' })
posts.forEach(post => {
stream.write({
url: `/blog/${post.slug}`,
lastmod: post.updatedAt
})
})
stream.end()
const sitemap = await streamToPromise(Readable.from(stream))
await writeFile('public/sitemap.xml', sitemap)
}
}
})
Pro Tip
9 Performance Optimization
Optimizing your Nuxt 3 application for maximum performance
Implement key performance optimizations to ensure your Nuxt 3 blog loads quickly and runs smoothly.
// nuxt.config.ts
export default defineNuxtConfig({
experimental: {
payloadExtraction: true,
inlineSSRStyles: false
},
nitro: {
prerender: {
routes: ['/sitemap.xml', '/rss.xml'],
crawlLinks: true
},
compressPublicAssets: true
},
image: {
provider: 'ipx',
presets: {
blog: {
modifiers: {
format: 'webp',
quality: 80,
loading: 'lazy'
}
}
}
},
app: {
head: {
htmlAttrs: { lang: 'en' },
link: [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{ rel: 'dns-prefetch', href: 'https://fonts.googleapis.com' }
]
}
}
})
Pro Tip
Anton Andresen
Full Stack Developer & Nuxt Enthusiast