Building a Blog with Nuxt Content: A Complete Guide

Creating a blog has never been easier with Nuxt Content. This powerful module transforms your Nuxt.js application into a content-driven website with minimal configuration. In this comprehensive guide, I'll walk you through everything you need to know to build a professional blog.

What is Nuxt Content?

Nuxt Content is a git-based headless CMS that provides a powerful set of features for content management:

  • Markdown Support: Write content in Markdown with frontmatter
  • Vue Components: Use Vue components directly in your content
  • Syntax Highlighting: Built-in code highlighting for multiple languages
  • Full-text Search: Powerful search capabilities
  • SEO Friendly: Automatic meta tag generation

Getting Started

Installation

First, let's install the Nuxt Content module:

npm install @nuxt/content

Configuration

Add the module to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@nuxt/content'],
  content: {
    highlight: {
      theme: {
        default: 'github-dark',
        dark: 'github-dark',
      },
    },
  },
})

Creating Your First Blog Post

Directory Structure

Create a content directory in your project root:

content/
  blog/
    my-first-post.md
    another-post.md

Writing Content

Here's an example blog post with frontmatter:

---
title: 'My First Blog Post'
description: 'This is my first blog post using Nuxt Content'
date: '2025-01-15'
category: 'Tutorial'
tags: ['nuxt', 'blog']
readTime: 5
---

# My First Blog Post

This is the content of my blog post written in **Markdown**.

## Code Example

````javascript
const greeting = "Hello, World!";
console.log(greeting);
\```
````

## Building Blog Pages

### Blog Index Page

Create a blog index page at `pages/blog/index.vue`:

```vue
<script setup>
const { data: posts } = await queryContent('blog').sort({ date: -1 }).find()
</script>

<template>
  <div>
    <h1>My Blog</h1>
    <article v-for="post in posts" :key="post._path">
      <NuxtLink :to="post._path">
        <h2>{{ post.title }}</h2>
        <p>{{ post.description }}</p>
      </NuxtLink>
    </article>
  </div>
</template>
```

### Dynamic Blog Post Page

Create a dynamic page at `pages/blog/[...slug].vue`:

```vue
<script setup>
const route = useRoute()
const { data: post } = await queryContent('blog', route.params.slug).findOne()

if (!post) {
  throw createError({
    statusCode: 404,
    statusMessage: 'Post not found',
  })
}
</script>

<template>
  <div>
    <header>
      <h1>{{ post.title }}</h1>
      <p>{{ post.description }}</p>
    </header>
    <ContentRenderer :value="post" />
  </div>
</template>
```

## Advanced Features

### Syntax Highlighting

Nuxt Content comes with built-in syntax highlighting powered by Shiki:

```javascript
// This code will be beautifully highlighted
const fibonacci = (n) => {
  if (n <= 1) return n
  return fibonacci(n - 1) + fibonacci(n - 2)
}
```

### Custom Components

You can use Vue components directly in your Markdown:

```markdown
::alert{type="success"}
This is a custom alert component!
::
```

### SEO Optimization

Use the `useSeoMeta` composable for SEO:

```javascript
useSeoMeta({
  title: post.title,
  description: post.description,
  ogTitle: post.title,
  ogDescription: post.description,
  twitterCard: 'summary_large_image',
})
```

## Content Querying

### Basic Queries

```javascript
// Get all blog posts
const posts = await queryContent('blog').find()

// Get posts with specific tag
const vuePosts = await queryContent('blog')
  .where({ tags: { $contains: 'vue' } })
  .find()

// Get recent posts
const recentPosts = await queryContent('blog').sort({ date: -1 }).limit(5).find()
```

### Advanced Filtering

```javascript
// Complex filtering
const filteredPosts = await queryContent('blog')
  .where({
    category: 'tutorial',
    date: { $gte: '2025-01-01' },
  })
  .only(['title', 'description', '_path'])
  .find()
```

## Styling Your Blog

### Dark Theme Implementation

```css
:root {
  --bg-primary: #0a0a0a;
  --text-primary: #ffffff;
  --text-secondary: #a0a0a0;
  --primary-glow: #00d4ff;
}

.blog-post {
  background: var(--bg-primary);
  color: var(--text-primary);
}

.blog-post h2 {
  color: var(--primary-glow);
}
```

### Responsive Design

```css
.post-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2rem;
}

@media (max-width: 768px) {
  .post-grid {
    grid-template-columns: 1fr;
  }
}
```

## Performance Optimization

### Image Optimization

Use Nuxt Image for optimized images:

```vue
<template>
  <NuxtImg src="/blog-image.jpg" alt="Blog post image" width="800" height="400" loading="lazy" />
</template>
```

### Lazy Loading

Content is automatically lazy-loaded for better performance:

```javascript
const { data: posts } = await queryContent('blog').limit(10).find()
```

## Best Practices

### 1. Consistent Frontmatter

Always use consistent frontmatter structure:

```yaml
---
title: 'Post Title'
description: 'Brief description'
date: '2025-01-15'
category: 'Category'
tags: ['tag1', 'tag2']
readTime: 5
---
```

### 2. SEO-Friendly URLs

Use descriptive slugs for your blog posts:

```
/blog/building-blog-with-nuxt-content
/blog/vue-3-composition-api-guide
```

### 3. Content Organization

Organize your content logically:

```
content/
  blog/
    2025/
      01/
        post-1.md
        post-2.md
  docs/
    getting-started.md
```

## Deployment

### Static Generation

Enable static generation for better performance:

```typescript
export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/blog', '/blog/sitemap.xml'],
    },
  },
})
```

### Automatic Deployment

Set up automatic deployment with GitHub Actions:

```yaml
name: Deploy to Production
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: Deploy
        run: npm run deploy
```

## Conclusion

Nuxt Content provides an excellent foundation for building modern, performant blogs. With its powerful querying capabilities, built-in SEO features, and seamless integration with Vue.js, you can create a professional blog that's both developer-friendly and user-friendly.

The combination of Markdown for content creation and Vue.js for dynamic functionality makes it an ideal choice for developers who want full control over their blog while maintaining ease of use.

Start building your blog today and join the growing community of developers using Nuxt Content for their content-driven applications!

---

_Happy blogging! 🚀_