Blog
A blog built with Nuxt Content: one markdown file per post, a validated frontmatter contract, complete SEO metadata, translations and a regression gate.
Nuxfire comes with a blog built with Nuxt Content. Add markdown files to start publishing: the build validates every post and generates its search and social metadata.
What's Included
- Blog index and post pages, with one
<h1>per post - Site-wide search integration
- Complete SEO per post: title, description, canonical, Open Graph and Twitter tags,
BlogPostingstructured data, language, hreflang and sitemaplastmod - Posts in several languages, linked as translations of each other
- A
bun run check:seogate that catches regressions - Responsive design and dark mode support
File Structure
Blog posts live in apps/web/content/blog, as their own Nuxt Content collection (apps/web/content.config.ts). Each post is one markdown file whose frontmatter is validated at build time:
---
title: "Specific title without the brand"
description: "One or two sentences that describe this post."
date: "2026-09-25"
author: "Your Name"
lang: en
ogImage: "/images/blog/my-cover.png"
---
Frontmatter
| Field | Required | Meaning |
|---|---|---|
title | Yes | The page title and the single <h1>. The brand is appended for you: do not write it. |
description | Yes | Search and social description of this post, never the site default. |
date | Yes | YYYY-MM-DD or an ISO 8601 datetime with a timezone. A date-only value means midnight UTC. |
updated | No | Same format, not before date. Feeds article:modified_time and the sitemap lastmod. |
author | Yes | The author name shown on the page and in the structured data. |
authorType | No | Person or Organization (default Organization). |
lang | Yes | en, pt-br or es. It has no default: it sets <html lang>, og:locale and hreflang. |
translations | Yes | Language to slug of every version of the post, itself included: one for each of en, pt-br and es. |
category | No | Shown on the card and used as article:section. |
readTime | No | Shown on the card, for example 8 min. |
tags | No | Used as article:tag and as keywords in the structured data. |
image | No | The cover shown on the post page. It can be an SVG. |
ogImage | No | The image social networks read: a .png or .jpg path under apps/web/public. Falls back to the default site image. |
Translations
Every post is written in all three languages, one file per language. Link the versions by repeating the same translations block in every one of them, with a key for each language; each key is the language of the post it points to:
translations:
en: my-post-english-slug
pt-br: my-post-portuguese-slug
es: my-post-spanish-slug
The blog index shows each post once, in the language the visitor is browsing in (English when that language has no version), and a post that was never translated stays visible in its own language. The head and the sitemap list every version reciprocally, with x-default pointing to the English one. bun run check:seo fails if a version is missing, is written in another language or does not point back, and it rejects a post that does not list all three languages. Give each version its own cover when the image contains text.
Cover images
Design the cover as a 16:9 SVG in apps/web/public/images/blog, then render the PNG that social networks read. Facebook's sharing documentation lists JPEG, GIF and PNG for og:image; SVG is not among them.
bun run generate:og
The command writes a 1200x675 PNG next to every SVG cover and next to the default site image (apps/web/public/images/og/default.svg), and running it twice changes nothing. It runs on your machine with sharp, so open each PNG and commit it.
Check Before You Publish
Build the site with its real address and run the gate against the generated pages:
SITE_URL=https://your-domain bun run --cwd apps/web build
bun run check:seo
- Every post has a language, valid dates, a raster
ogImagethat exists, and a consistent set of translations. - Every page has its own title and description, one
<h1>, an absolute canonical, a social image and, for posts,BlogPostingstructured data in the right language. - The sitemap lists every post with
lastmodand the same hreflang as the page head, and lists nothing that asks not to be indexed.
Without a build, the command still lints the frontmatter of every post and says that the page audit was skipped. To write posts with an AI agent, load the content specialist described in Nuxfire Stack Specialists.
Ready to build and launch your SaaS?
Get 100% full source code ownership, zero proprietary wrappers, and architecture engineered for millions of requests on Cloudflare.