---
order: 3
section: guides
title: Модель данных
description: >-
  Файлы, frontmatter, встроенные поля, редиректы и проверки, которые выполняет
  scribe validate.
noindex: false
canonicalPath: /ru/docs/content-model
---
## Файлы

Один документ — это один файл `.mdx` (или `.md`) в папке типа контента:

```text
content/
  blog/
    hello-world.mdx        → слаг "hello-world"
    _redirects.json        → правила редиректов для этого типа (опционально)
  authors/
    jane.mdx               → слаг "jane"
```

- **Имя файла является английским слагом**. Слаги пишутся строчными буквами через дефис (kebab-case).
- На диске хранятся только английские файлы. Локализованные версии живут в базе SQLite.
- Файлы, имя которых начинается с `_` или заглавной буквы (например, `PUBLISHING.md`), игнорируются. Вы можете хранить в них заметки прямо рядом с контентом.

## Frontmatter

Frontmatter пишется на YAML и проверяется на соответствие схеме Zod вашего типа контента:

```mdx
---
title: "Привет, мир"
description: "Достаточно длинное описание для схемы."
author: jane
publishedAt: "2026-01-15"
updatedAt: "2026-02-01"
---

Основной текст в формате MDX.
```

Валидация frontmatter подчиняется вашей схеме Zod: при обычном `z.object` неизвестные ключи просто отбрасываются. Если хотите, чтобы опечатки в названиях полей вызывали ошибку, используйте `.strict()`.

## Встроенные поля frontmatter

Эти поля доступны для **любого** типа контента, и их не нужно объявлять в схеме. Они извлекаются из frontmatter до запуска вашей схемы, поэтому добавлять их в схему Zod бессмысленно:

| Поле | Тип | Описание |
| --- | --- | --- |
| `publishedAt` | Дата ISO | Дата публикации. |
| `updatedAt` | Дата ISO | Дата последнего значимого обновления. По умолчанию совпадает с `publishedAt`. Используется для `lastModified` в sitemap. |
| `noindex` | boolean | Исключает документ из sitemap. Выведите это значение как метатег robots на ваших страницах. |
| `canonicalPath` | string | Ручное переопределение канонического URL-пути. |

Локализованные документы наследуют `publishedAt`, `updatedAt`, `noindex` и `canonicalPath` от английского оригинала. Переводчики не могут их менять.

Каждый загруженный документ также содержит свойства `slug`, `enSlug` (слаг английского оригинала, который совпадает с `slug` для английских документов), `locale`, `frontmatter` и `content`.

## Типы контента без тела документа

Справочные коллекции (типы вроде `model` или `category`, схема которых носит исключительно структурный характер) часто вообще не имеют MDX-тела. Чтобы явно указать это, добавьте `body: false` в настройках типа:

```ts
defineContentType({
  id: "model",
  contentDir: "models",
  schema: modelSchema,
  body: false, // записи содержат только frontmatter
});
```

По умолчанию используется `body: true`, что обеспечивает полную обратную совместимость. Для типа с `body: false` наличие любого текста кроме пробелов в теле документа вызовет ошибку валидации, загрузчик пропустит парсинг MDX, а статический экспорт не будет генерировать тело. Тип без тела документа, у которого **нет** переводимых полей, вообще исключается из процесса перевода (никакого лишнего шума о пропущенных или устаревших переводах). Если же у типа с `body: false` есть хотя бы одно переводимое поле, он остается в списке задач с данными только из frontmatter. Правила переводимости описаны в разделе [Перевод](/docs/translation).

## Больше, чем frontmatter

MDX позволяет делать больше, чем просто писать текст:

- [Встроенные токены](/docs/inline-tokens) внедряют ссылки, URL-адреса ресурсов и непереводимые строковые литералы прямо в текст, разрешая их для каждой локали при чтении.
- [Ресурсы](/docs/assets), объявленные через `field.asset()`, проверяются на диске и преобразуются в публичные URL-адреса во время загрузки.

## Редиректы: `_redirects.json`

В папку любого типа контента можно добавить файл `_redirects.json`, чтобы объявить правила изменения слагов или перенаправления для удаленных документов. Редиректы продолжают работать даже после удаления исходного MDX-файла. Слаги переведенных версий автоматически извлекаются из SQLite.

```json
{
  "redirects": [
    { "from": "hello-world", "toSlug": "hello-scribe" },
    { "from": ["old-a", "old-b"], "toSlug": "hello-scribe" },
    { "from": "moved-post", "toType": "glossary", "toSlug": "virtual-try-on" },
    { "from": "retired-page", "toUrl": "/pricing" },
    { "from": "retired-ext", "toUrl": "https://example.com/app" }
  ]
}
```

Существует три типа редиректов (для каждой записи указывается ровно одна цель):

| Тип | Поля | Описание |
| --- | --- | --- |
| Тот же тип | `toSlug` | Целевой английский слаг в том же типе контента. URL формируется на основе `path` этого типа и локализуется для каждого языка. |
| Другой тип | `toType` + `toSlug` | Целевой английский слаг в другом типе контента с маршрутизацией (должен иметь `path`). |
| Произвольный URL | `toUrl` | Относительный путь от корня на том же сайте или абсолютный внешний URL, одинаковый для всех локалей. |

- `from`: только английские слаги. Слаги переведенных исходников извлекаются из SQLite.
- Необязательный параметр `permanent` (по умолчанию `true`).

Чтобы удалить или переименовать документ, добавьте запись в `_redirects.json`, удалите (или переименуйте) исходный MDX-файл, затем запустите `scribe validate` и выполните сборку. Правила редиректов генерируются функцией `buildAllContentRedirects()` для конфигурации вашего прокси-сервера или фреймворка.

## Валидация

```bash
scribe validate
```

Проверяет каждый английский файл: соответствие схеме, формат встроенных полей, ваш хук `crossValidate` и **компиляцию MDX**. Если тело не парсится как MDX, сборка блокируется с ошибкой — это касается как английских оригиналов, так и сохраненных переводов.

В масштабе всего проекта также проверяются: целостность связей (отсутствие обязательной связи — ошибка, отсутствие необязательной связи — предупреждение), правила в `_redirects.json` (корректные цели, отсутствие дублирующихся источников или цепочек редиректов), правила суффиксов для локализованных слагов, [объявленные поля ресурсов](/docs/assets) (наличие файлов, `formats`, `maxKB`), [встроенные токены](/docs/inline-tokens) (некорректные теги span, отсутствующие связи, `:href` на типы без маршрутизации, пропущенные ключи `vars`, отсутствующие файлы ресурсов), типы с `body: false`, которые по-прежнему содержат текст, отсутствие изображений при заданной директории ресурсов и наличие базы переводов.

Код возврата не равен нулю, если найдена хотя бы одна ошибка. Запускайте эту команду перед сборкой:

```json
{
  "scripts": {
    "build": "scribe validate && <команда сборки вашего фреймворка>"
  }
}
```
