Блог (MDX + RSS)

Блог на MDX-файлах: посты лежат в content/blog/*.mdx с YAML-фронтматтером, страница списка и страница поста генерируются статически, есть валидный RSS-фид на /rss.xml.

Из чего состоит

ФайлНазначение
content/blog/*.mdxПосты с фронтматтером title, date, description, slug.
src/lib/blog/posts.tsЧтение/валидация постов (gray-matter + Zod): getAllPosts, getPostBySlug, getAllPostSlugs.
src/lib/blog/rss.tsГенерация RSS 2.0 (buildRssXml) с экранированием XML.
src/app/[locale]/blog/page.tsxСписок постов (/blog, /en/blog).
src/app/[locale]/blog/[slug]/page.tsxСтраница поста, рендер MDX через next-mdx-remote/rsc.
src/app/rss.xml/route.tsRSS-фид на /rss.xml.

Фронтматтер поста

---
title: Заголовок поста
date: 2026-06-01
description: Короткое описание для списка, SEO и RSS.
slug: url-slug
---

# Обычный Markdown/MDX

Тело поста…

Если slug не указан, используется имя файла без расширения. Дата в YAML может быть без кавычек (2026-06-01) — она нормализуется в строку YYYY-MM-DD.

Добавить пост

  1. Создайте content/blog/my-post.mdx с фронтматтером.
  2. Готово — пост появится в /blog, на своей странице /blog/my-post и в /rss.xml (список отсортирован по дате, новые сверху). Slug'и статически пре-рендерятся через generateStaticParams, поэтому чтения файлов в рантайме нет.

RSS-фид

/rss.xml (src/app/rss.xml/route.ts) отдаёт валидный RSS 2.0 (content-type: application/rss+xml), построенный чистой функцией buildRssXml: канал с title / link / description, atom:link на себя и по <item> на каждый пост (title, link, guid, pubDate, description) со спецсимволами, экранированными в XML. Фид вычисляется на этапе сборки (force-static), так что в рантайме доступа к файловой системе нет.

Подсветка синтаксиса (опционально)

Базовый рендер MDX включён без подсветки. Чтобы добавить её, подключите rehype-плагин (rehype-pretty-code / rehype-highlight) в options.mdxOptions.rehypePlugins компонента MDXRemote в src/app/[locale]/blog/[slug]/page.tsx.

Дальше

  • SEO и метаданные — посты блога попадают в sitemap.xml, а страница поста задаёт свои title / description.