Harnessing Nuxt Content v2 for File‑Based Blogs: Auto‑Generated Routes, ISR & SEO
Learn how Nuxt Content v2 turns Markdown files into auto‑generated routes, supports incremental static regeneration, and injects SEO meta tags from frontmatter. Follow a step‑by‑step guide to set up a file‑based blog in Nuxt 3.
04 Feb 2026, 01:07 UTC

Problem: Manual Routing and Repeated API Calls for a Blog
When building a blog with Nuxt 3 you often start with a pages/blog/_slug.vue file and manually query a headless CMS or a local JSON file. Each new post requires you to update routes, update the sitemap, and tweak meta tags for SEO. This workflow is error‑prone and hard to maintain.
Takeaway: Nuxt Content v2 turns every Markdown file in content/ into a fully‑featured page with auto‑routing, static generation, and built‑in SEO support. It also exposes a lightweight JSON API and supports Incremental Static Regeneration (ISR) out of the box.
1. The File‑Based Content Layer
Nuxt Content creates a virtual file system under content/. Each Markdown file becomes a document that can be queried with the new useContent composable. The file structure maps directly to URLs:
content/
├─ blog/
│ ├─ hello-world.md
│ └─ advanced‑nuxt.md
└─ about.md
Resulting routes:
/blog/hello-world/blog/advanced-nuxt/about
2. Auto‑Generated Routes & Built‑In API
At build time, Nuxt scans content/ and creates:
- Static HTML files in
dist(ifssgis enabled). - Runtime API routes under
/api/contentthat return JSON for each document.
Example API call:
GET /api/content/blog/hello-world.json
This endpoint is useful for headless clients or for debugging.
3. Incremental Static Regeneration (ISR)
Nuxt 3’s Nitro backend supports ISR. When you fetch a document with useAsyncData and set swr: true, the page is regenerated on the first request after a specified interval. This keeps content fresh without a full rebuild.
const { data } = await useAsyncData(
'post',
() => queryContent('blog', 'hello-world').findOne(),
{ swr: true, swrInterval: 60000 }
)
Key points:
- Requires Nitro v1.0+ (Nuxt 3.0+).
- If you run
npm run dev, ISR is disabled; usenpm run generateornpm run previewto test. - The generated HTML is cached on the server; subsequent requests hit the cache until the interval expires.
4. SEO from Frontmatter
Each Markdown file can include YAML frontmatter. Nuxt Content automatically injects these values into the page’s head() composable, allowing per‑page meta tags without manual code.
---
# hello-world.md
title: "Hello, World!"
description: "My first Nuxt blog post."
image: "/images/hello-world.png"
---
# Hello, World!
Content goes here.
In the page component you can expose the frontmatter to head():
useHead({
title: data.value?.title,
meta: [
{ name: 'description', content: data.value?.description },
{ property: 'og:image', content: data.value?.image }
]
})
5. Migration & Trade‑offs
- From Nuxt 2 / nuxt‑content v1: The folder layout changed;
content/now supports nested collections. You must updateuseContentqueries and replacenuxt-contentwith the newnuxt/contentmodule. - TypeScript strict mode: Run
npx nuxi prepareafter adding content files to generate/.nuxt/content.d.ts. Without this, the compiler may throw “Cannot find name 'Content'” errors. - ISR fallback: Older Nuxt 3 releases (pre‑3.2) do not support ISR fallback routes. If you need this feature, upgrade to Nuxt 3.2+.
- Server load: While static generation reduces load, ISR introduces runtime regeneration. Monitor
nitrologs for regeneration spikes during content updates.
6. Actionable Steps to Get Started
- Install the module:
npm i @nuxt/content - Configure in
nuxt.config.ts: - Add Markdown files to
content/and commit frontmatter. - Generate the site:
npx nuxi generateornpm run generate.- Verify routes by running
npx nuxi devand visiting/blog/hello-world. - Check the generated API route:
/api/content/blog/hello-world.json.
- Verify routes by running
- Enable ISR (optional): In the page component, add
swr: truetouseAsyncDataas shown earlier. - Deploy: Use any static host (Netlify, Vercel) or a Node server to serve the Nitro build. ISR works on serverless runtimes that support Nitro’s caching.
export default defineNuxtConfig({
modules: ['@nuxt/content'],
content: {
documentDriven: true, // enables auto‑routes
ssg: true, // static site generation
apiPrefix: '/api/content'
}
})
Conclusion
Nuxt Content v2 gives you a zero‑configuration, file‑driven blog engine that handles routing, static generation, incremental updates, and SEO automatically. The trade‑offs are mainly around migration effort and ISR limitations in older releases. With the steps above, you can spin up a production‑ready blog in minutes and focus on writing content instead of plumbing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.