Перейти к содержимому
Версия 1.0 ещё не выпущена; проект находится на стадии pre-MVP. См. возможности и ограничения версии 1.0.

Сайты-блоги

Сайт создаётся как Сайт или как Блог. Выбор делается один раз, при создании сайта, и потом не меняется.

  • Сайт: сначала страницы. Собственные модели контента добавляйте в разделе Конструктор контента, когда они понадобятся.
  • Блог: сначала посты. Dee Wan добавляет одну небольшую модель Post и показывает Записи в главной навигации.

Сайты, созданные до появления этого выбора, — это Website.

После создания записи сайта Dee Wan запускает настройку блога. Настройка добавляет одну обычную модель контента:

Поле Тип Обязательное Язык
title текст да для каждого языка
cover медиа нет для каждого языка
body форматированный текст да для каждого языка
publication_date дата нет общая для всех языков

Модель — Post (слаг post), локализованная, с title в качестве отображаемого поля. Настройка не добавляет компонентов, категорий, ключевых слов или других моделей. Категории, теги и указанные авторы — необязательное дополнение: см. категории, теги и авторы.

Адрес поста — обычный адрес контента (его слаг). publication_date — дата, которую вы показываете читателям. Она ничего не публикует.

Для постов действует тот же жизненный цикл, что и для записей других моделей: редактор, проверка данных, версии, процесс согласования, проверка редактором, публикация, снятие с публикации, история и права доступа. Пост публичен, только когда он опубликован. Черновики никогда не появляются в публичном блоге или в Latest posts.

Публикация поста не пересобирает сайт. Страницы блога читают опубликованные посты в момент запроса.

На сайте-блоге боковая панель такая:

  • Основное: Обзор, Записи, Страницы и Планировщик для пользователей с правом создавать тексты с помощью ИИ (ai:generate).
  • Дополнительно: Контент и Конструктор контента для тех, кто может читать модели.
  • Конфигурация: Настройки и Установка для суперадминистраторов.

Пункт, которым ваша роль пользоваться не может, не показывается, а пустая группа пропускается.

Навигация Website не меняется.

Записи — это представление модели post в обычном списке контента: поиск, фильтры рабочего процесса, обложка, заголовок, адрес, дата публикации, состояние и обычные действия строки. Создать пост и открытие поста используют обычный редактор контента; его хлебные крошки и Отмена возвращают в Записи.

Контент и Конструктор контента по-прежнему показывают все модели, включая post.

Адрес Что показывает
/blog Опубликованные посты, по 12 на страницу
/blog?page=2 Следующие 12 и так далее
/blog/<post-slug> Один опубликованный пост: заголовок, обложка, дата публикации, текст
/blog/category/<slug> Опубликованные посты одной категории, по 12 на страницу
/blog/tag/<slug> Опубликованные посты с одним тегом, по 12 на страницу
/blog/author/<slug> Опубликованные посты, где указан один человек, по 12 на страницу

Вне языка по умолчанию те же адреса начинаются с кода языка, например /th/blog, по существующей маршрутизации локалей сайта и правилу резервного языка. Пост отвечает по собственному слагу на каждом языке: /th/blog/<thai-post-slug>.

  • Посты идут от новейшей publication_date. Посты без даты идут последними.
  • page должен быть положительным целым числом. Страница за концом списка отвечает 404.
  • Блог без опубликованных постов показывает пустую страницу блога, а не 404.
  • Отсутствующий, черновой, снятый с публикации пост или пост на недоступном языке отвечает 404.

Страница, маршрут Site Chrome или перенаправление не могут использовать /blog или что-либо под ним на сайте-блоге. Такой конфликт блокирует рендер с blog_route_conflict, пока вы не измените один из адресов. Одно исключение: перенаправление может начинаться с собственного адреса поста (/blog/<post-slug>), который не использует ни один опубликованный пост, чтобы пост, опубликованный под новым адресом, сохранил рабочую старую ссылку. Настройки Поиск и соцсети поста применяются к его странице.

У каждого языка блога есть лента RSS 2.0 из 20 новейших опубликованных постов:

Адрес Лента
/rss.xml Посты на языке сайта по умолчанию
/<code>/rss.xml Посты на другом языке, /th/rss.xml

В каждом элементе есть заголовок поста, его полный адрес, краткое описание, указанные авторы и дата публикации. Описание — это поисковое описание поста или начало его текста. Пост уходит из ленты сразу, как только его снимают с публикации или перемещают в корзину, без пересборки. Каждая страница блога указывает адрес своей ленты в секции head, поэтому RSS-клиент может найти её по адресу страницы. У языка без собственного адреса блога своей ленты нет.

Посетители могут комментировать опубликованные посты. Комментарии выключены, пока вы не включите их в Записи → Комментарии с помощью Принимать новые комментарии. Этот переключатель — настройка Комментарии посетителей модели post, та же, что есть у любой модели; см. комментарии посетителей. Выключение скрывает все комментарии и отклоняет новые; ничего не удаляется.

Новые комментарии ожидают модерации и не показываются посетителям, пока вы их не одобрите. Каждый комментарий находится в состоянии Ждут, Одобрены, Спам или Отклонены. Одобрите, отклоните или отметьте как спам один комментарий или до 25 выбранных сразу. Удалить навсегда удаляет комментарий и ответы на него.

Действие Право
Чтение и модерация content:publish
Окончательное удаление content:publish и удаление в post
Включение и выключение комментариев site:settings в Записи → Комментарии или model:apply для переключателя Комментарии посетителей модели в разделе Конструктор контента
Отметить Helpful от своего имени чтение в post

Каждое действие отправляет состояние, которое вы видели. Комментарий, который кто-то другой тем временем перевёл в другое состояние, остаётся как есть, а список загружается заново. Модерация никогда не отправляет уведомлений.

  • Комментарий принадлежит своему посту и одному языку, а не адресу. Переименование поста сохраняет комментарии. У каждого языка своя ветка.
  • Один уровень ответов. Ответ можно оставить на одобренный комментарий верхнего уровня того же поста и языка.
  • Посетители и участники команды могут отметить одобренный комментарий Helpful, каждый один раз. Счётчик виден у комментария, а Most helpful упорядочивает комментарии по нему. Кто отреагировал, никогда не показывается.
  • Снятие поста с публикации или перемещение в корзину скрывает его комментарии. Повторная публикация показывает их снова.
  • Удалить навсегда в корзине удаляет и комментарии поста, как и автоматическое удаление после срока хранения в корзине. В окне подтверждения указано их количество.
  • Комментарий хранит отображаемое имя, необязательный сайт, необязательный адрес электронной почты, текст, согласие, время и состояние. Адрес почты приватен: он не попадает ни в ответы публичного API, ни на страницу, ни в кеш. Dee Wan никогда не пишет посетителю. Комментарий без адреса почты показывает Не указана в подробностях.
  • Форма просит имя, комментарий и согласие. Сайт и почта необязательны и проверяются, только когда заполнены. Согласие касается только того, что вводит посетитель.
  • Комментарий, импортированный без согласия, например из экспорта WordPress, показывает Нет согласия. Источник никогда не записывал, что человек принял форму комментариев этого сайта, и ничто в Dee Wan этого не меняет. После импорта он ожидает модерации, и посетители его не видят. Опубликовать импортированный комментарий… показывает его посетителям после подтверждения в диалоге. Это ваше решение опубликовать его снова; согласие при этом не записывается, и комментарий сохраняет Нет согласия. Настройки → История записывает, кто и когда его опубликовал, но никогда не текст. Массовое одобрение пропускает такие комментарии и сообщает, сколько из них нужно проверить по одному. Отклонить, Пометить как спам и Удалить навсегда остаются доступны. Перевод опубликованного импортированного комментария из состояния Одобрены снова его скрывает; чтобы показать его снова, опять нужен Опубликовать импортированный комментарий….
Ограничение Значение
Имя 80 символов
Сайт 200 символов, https:// или http://
Почта 254 символа, необязательно
Комментарий 4 000 символов
Комментарии на клиента и сайт 10 за 10 минут, отдельно от форм
Реакции на клиента и сайт 60 за 10 минут, отдельно от комментариев
Ответы, показанные под одной веткой 20
Показанный счётчик до 999, затем 999+

Каждая отправка формы содержит ключ. Повторная отправка того же комментария с его ключом получает первую квитанцию; тот же ключ с другим текстом отклоняется. Скрытое поле ловит простых ботов. Для ограничения частоты используется хеш адреса посетителя с ключом, а не сам адрес, и счётчик стирается через сутки.

Подписи публичных комментариев пока на английском.

Страница поста показывает одобренные комментарии, по 20 веток на страницу (?comments_page=2), и форму. Посетители сортируют их Oldest (по умолчанию), Newest или Most helpful (?comments_order=), и у каждого комментария есть кнопка Helpful. Форма работает без JavaScript: она отправляет данные на /v1/interactions/comment.submit на собственном хосте сайта и возвращает к посту с результатом; Helpful так же отправляет на /v1/interactions/comment.react. Сгенерированный сайт также отправляет форму на месте и показывает состояния занятости, ошибки, повтора, лимита и успеха, не покидая страницу. Предпросмотр никогда не принимает комментарий. Маршрут приёма <host>/v1/interactions/* должен вести к Worker приёма, как и для форм сайта. Рендереры читают комментарии из GET /v1/_comments; см. публичный API.

Копия сайта и перенос истории сайта несут комментарии каждого экспортированного поста в comments.jsonl с их состоянием, приватной почтой (или null, если её не дали) и счётчиками реакций. Кто реагировал, не переносится. Импорт воссоздаёт их на постах, созданных этим импортом, а ответы — в их собственных ветках. Повторный импорт той же копии никогда их не дублирует, а отмена импорта их удаляет. После импорта комментарий без согласия всегда ожидает модерации, даже если на исходном сайте он был опубликован: опубликуйте его на этом сайте снова, если хотите его показать. Экспорт в таблицы не включает комментарии. Импорт из WordPress приносит комментарии читателей на модерацию и без согласия; см. импорт из WordPress. Импорт из Strapi никогда не создаёт комментарии. Резервная копия базы данных включает их, как и все данные сайта.

Необязательное дополнение для готового блога. Откройте Записи, нажмите ⋯, затем Добавить категории, теги и авторов, затем Добавить. Нужно право менять модели (model:apply). Пункт меню показывается, пока у модели post нет хотя бы одного из трёх полей ниже.

Дополнение добавляет обычные модели и поля, и ничего больше:

Модель Слаг Поля
Category category name (текст, обязательное, для каждого языка), parent (одна другая категория, необязательно)
Tag tag name (текст, обязательное, для каждого языка)
Person person name (текст, обязательное, для каждого языка), bio (короткий текст, для каждого языка), photo (медиа, для каждого языка)

и три поля связи «многие ко многим» в post: categories → category, tags → tag и authors → person. Три модели публичны и показывают name. Все три переводятся: у каждого языка своё имя и свой адрес. Биография и фото человека тоже принадлежат каждому языку. parent и список authors поста общие для всех языков.

  • Конструктор контента после этого владеет их структурой, как и любой другой модели.
  • Редактор поста назначает их обычными полями связи. Авторы показываются в том порядке, в каком их добавили к посту; чтобы изменить порядок, удалите автора и добавьте снова.
  • Автор — это имя, указанное в публикации, а не учётная запись. Он никогда не связан с пользователем, с тем, кто создал пост или владеет им, или с тем, кому назначен шаг рабочего процесса.

Добавление можно безопасно повторять. Всё, что уже есть и совпадает, сохраняется. Если модель category, tag или person уже существует и отличается, или у post уже есть отличающееся поле categories, tags или authors, ничего не добавляется, и панель перечисляет каждое такое место. Модель category, tag или person без перевода показывается как модель с другими языковыми настройками. Переименуйте или удалите её в разделе Конструктор контента, затем нажмите Повторить. Все модели и поля добавляются вместе или не добавляются вовсе.

parent — иерархическая связь. Сохранение, которое делает категорию собственным родителем или помещает её под одну из её же подкатегорий, отклоняется, и сообщение показывается у поля Parent category. Восстановленная версия подчиняется тому же правилу. В разделе Конструктор контента это переключатель Иерархия (родитель/потомок), который предлагается для любой связи «к одному» со своей же моделью; см. модели и поля. Сгенерированный автономный API сохраняет parent и отклоняет те же циклы внутри своей записи в базу данных.

В Записи выберите посты, нажмите Категории и теги, выберите Категории или Метки, затем Добавить или Убрать, отметьте до 10 элементов и примените. Каждый пост сохраняет новую черновую версию со своими правами и проверкой версии. Ничего не публикуется. Пост, у которого изменение уже есть, остаётся как есть. Пост, который тем временем изменился, который вам нельзя менять или чьи поля нужно исправить, показывается как неизменённый с причиной. Авторы здесь не предлагаются.

Действуют обычные правила контента. Опубликованный элемент нужно снять с публикации, прежде чем он попадёт в корзину, а снятие с публикации перечисляет посты, которые на него ссылаются. В корзине он сохраняет свои связи, и Восстановить возвращает его. Удалить навсегда удаляет элемент и его связи из постов, а сами посты сохраняет.

Страница поста показывает By и авторов под заголовком, а категории и теги — после текста. Каждое имя ведёт на свой архив: /blog/category/<slug>, /blog/tag/<slug> или /blog/author/<slug>, с языковым префиксом вне языка по умолчанию.

  • Пост использует текущие опубликованные имена и адреса категорий, тегов и авторов. Опубликуйте исправление связанной записи: сохранять и публиковать сам пост заново не нужно. Изменения в черновиках не видны посетителям. Снятые с публикации, удалённые, приватные записи и записи в корзине не показываются.
  • Публичный кеш обновляется по обычным правилам очистки и срока хранения. Текст поста и его сохранённые версии не меняются.
  • На каждом языке категория, тег или автор показывает собственное имя и ведёт на собственный адрес. При строгом языковом правиле элемент без этого языка на посте не показывается. При резервном языке он показывается на языке, к которому откатывается сайт. Архив перечисляет посты, которые показывают этот адрес на его языке. Лента указывает авторов так же.
  • Архив перечисляет опубликованные посты, напрямую связанные с этим элементом, от новейшей publication_date, по 12 на страницу. Посты подкатегорий не включаются. Архив без опубликованных постов отвечает 404.
  • Блог без дополнения отвечает 404 по этим адресам.

Если у post есть поле с именем categories, tags или authors, которое не является связью с category, tag или person, блог не готов к рендеру (blog_contract_drift), пока поле не вернут обратно.

body поста — один форматированный документ, хранимый как канонический HTML. Каждое сохранение его проверяет: разметка вне документа отклоняется с указанием (поле, язык, элемент или атрибут), и ничего не записывается. Предпросмотры и рендереры Dee Wan никогда не вставляют хранимое значение как есть: оба рендерера рисуют его функцией renderRichDocument из контракта страницы.

Документ содержит абзацы, заголовки, списки, цитаты, блоки кода, разделители, жирный, курсив, подчёркивание, зачёркивание, встроенный код, нижний и верхний индексы, ссылки и изображения, а также:

  • таблицы до 12 столбцов и 200 строк с необязательной подписью, строкой заголовков и заголовками строк. Широкая таблица на телефоне прокручивается внутри своего блока;
  • галереи изображений из 2–24 изображений медиатеки, каждое с необязательной подписью;
  • блоки аудио, видео и файла, указывающие один файл медиатеки этого вида. Аудио и видео воспроизводятся на странице, со ссылкой на скачивание под плеером; файл — это ссылка с его именем, типом и размером;
  • вставки, создаваемые вставкой одной ссылки https: YouTube и Vimeo встроены, а администратор может разрешить другие источники (см. ниже). Блок хранит идентификатор провайдера, канонический адрес https и заголовок. Он никогда не хранит разметку, скрипт или CSS.
  • блоки плагинов, объявленные установленным плагином (см. ниже). Блок хранит свой тип, версию, с которой был сохранён, и значения полей. Он никогда не хранит разметку, скрипт или CSS.

Ссылки могут быть относительными, http, https, mailto или tel. Изображения могут быть относительными, http или https. Внешние ссылки получают rel="noopener noreferrer".

Публичный API отдаёт проверенный HTML. Блоки медиа и вставок — это данные, а не плееры. Если вы делаете собственный рендерер, рисуйте их через renderRichDocument или собственный рендерер того же документа.

Активный плагин может объявить типы блоков форматированного текста в своём манифесте (rich_blocks, см. plugins/authoring.md). Редактор перечисляет их в Блоки, рисует их поля собственными элементами управления и показывает предпросмотр каждого блока по объявленному плагином дереву рендера. Ничего от плагина не выполняется ни в редакторе, ни на сайте.

  • Хранимая форма: <figure data-block="plugin" data-type="<plugin id>/<name>" data-version="2" data-values="{...}"> с одним пустым <a data-field data-media-id href> на каждое поле медиа. Значения — строки, числа и булевы значения в виде отсортированного JSON. Поля медиа закрепляются, копируются и переназначаются как любые медиа медиатеки.
  • Сохранение, которое добавляет или меняет блок, проверяется по активным плагинам сайта: неизвестный тип отклоняется с rich_block_unregistered, версия новее объявленной — с rich_block_version_unknown, а значения, которые отклоняют объявленные поля, — с rich_block_values_invalid (каждый отказ называет поле и язык). Блок, сохранённый под более старой объявленной версией, принимается, когда его перенесённые значения проходят проверку, и хранится в присланном виде.
  • Блок, который уже есть в том же поле и языке, продолжает сохраняться, когда его плагин выключен или удалён. Редактор показывает его как сохранённый и не показываемый на сайте. Импорт и копии сайта переносят блоки с их версиями, что бы ни было установлено в месте назначения.
  • Старые блоки переходят на текущую версию, только когда об этом просит автор: открытие формы блока или Обновить на блоке, или Блоки → Обновить блоки ({count}). Опубликованный контент никогда не переписывается массово.
  • Рендереры читают определения из GET /v1/_rich-blocks только для страницы с блоком плагина и рисуют каждый блок адаптером хоста: фиксированный список элементов, каждое значение экранировано, каждый адрес проверен. Когда ни один адаптер не рисует блок (плагин не активен, нет дерева рендера или версия новее определения), публичная страница ничего на его месте не показывает, а предпросмотр показывает заглушку с его названием.
  • Поисковый текст, поисковые отрывки и описания в ленте включают текстовые значения блока и значения textarea, а также подписи выбранных значений select, прочитанные через определение активного плагина при сохранении. Блок без активного определения не добавляет слов. Приватные поля не добавляют их в любом случае.
  • Сниппеты следуют тем же правилам сохранения: сниппет, который добавляет или меняет блок плагина, проверяется по активным плагинам; неизменённый блок сохраняется.
  • Редактор перечисляет под полем каждый блок, который сайт не покажет, и почему (плагин не установлен, плагин выключен, более новая версия, нет раскладки). Выбор пункта в списке выделяет соответствующий блок.
  • Управляемые и сгенерированные сайты читают определения вживую, а не из данных генерации: их посты и списки блога тоже читаются вживую, поэтому зафиксированная копия определений устарела бы сразу, как только плагин установят, обновят или выключат. Сводки в областях сайта, зафиксированные при сборке сгенерированного сайта, не отображают блоки плагинов.

Настройки → Интеграции → Встраивания перечисляет встроенные плееры YouTube и Vimeo и источники, которые этот сайт может встраивать во фрейм. Только люди с site:infra видят этот экран и меняют список. Редактор читает список для каждого участника сайта, поэтому любой, кто может править пост, может вставить разрешённую ссылку.

  • Источник — это https:// и один точный хост с необязательным портом. Без пути, запроса, фрагмента, пароля, подстановочных знаков, IP-адреса или локального имени. Домен YouTube или Vimeo отклоняется: они встроены.
  • Сайт держит не более 20 источников, у каждого имя от 1 до 60 символов.
  • Ссылка YouTube на просмотр, «поделиться», Shorts, трансляцию или плеер становится адресом youtube-nocookie.com/embed/… с повышенной приватностью. Ссылка Vimeo становится player.vimeo.com/video/…?dnt=1. Ссылка на разрешённом источнике встраивается как есть. Всё остальное отклоняется с указанием причины: embed_url_malformed, embed_url_not_https, embed_url_credentials, embed_url_ambiguous (ссылка провайдера, которая не указывает одно видео) или embed_provider_unknown.
  • Редактор никогда не загружает провайдера. Он показывает заглушку, а Просмотр открывает адрес в новой вкладке.
  • Оба рендерера рисуют одинаковый фрейм: sandbox="allow-scripts allow-same-origin allow-presentation allow-popups allow-popups-to-escape-sandbox", allow="encrypted-media; picture-in-picture; fullscreen", referrerpolicy="strict-origin-when-cross-origin", loading="lazy" и блок 16:9. Ни одна запись его не меняет.
  • Рендереры читают разрешённые источники из GET /v1/_embeds только для документа с такой вставкой. frame-src управляемой страницы называет только встроенные плееры и эти источники.
  • Сохранение, которое добавляет или меняет вставку с источника не из списка, отклоняется с rich_embed_origin_not_allowed с указанием поля и языка. Это действует для редактора, API управления, плагинов и импорта таблиц. Вставка, которая уже есть в том же поле и языке, продолжает сохраняться после удаления её источника, а восстановление старой версии не отклоняется: такие вставки рисуются как обычные ссылки, пока источник не добавят снова. Копия сайта или импорт из Strapi переносят вставки, которые были в источнике, так же. Ничто не встраивает источник, которого нет в списке.
  • Изменять список можно только на этом экране. Общий API настроек отказывается создавать, менять или удалять строку embed_providers (setting_server_owned).

Сайт сохраняется, что бы ни случилось во время настройки, а раздел Записи показывает, что делать:

  • Настройка блога не завершилась (например, при сбое сети): нажмите Повторить. Ничего не было отмечено как готовое.
  • Настройку блога блокирует существующая модель «post»: на сайте уже есть модель со слагом post, которая не совпадает со стартовой. Dee Wan оставляет её без изменений. Нажмите Открыть конструктор контента, переименуйте или удалите эту модель или приведите её в соответствие, затем нажмите Повторить.

Состояние хранится вместе с сайтом, поэтому после перезагрузки виден тот же экран. Публичный блог недоступен, пока настройка не завершилась.

Последние посты — секция для любой страницы. Добавьте её через Добавить раздел → Шаблоны блоков → Последние посты. Она показывает шесть новейших опубликованных постов с обложкой, заголовком и датой публикации.

Это предустановка секции Последние записи, которая может показывать любую публичную коллекцию. В инспекторе выберите:

  • Коллекция: модель для списка. Она должна быть публичной.
  • Поле заголовка и при желании Поле изображения, Поле описания и Поле даты.
  • Сколько: от 1 до 12.
  • Текст, когда ничего не опубликовано: показывается, только когда в коллекции нет опубликованных записей.

Когда выбрано поле даты, записи идут от новейшей по этой дате. Иначе они идут от последних опубликованных.

Страница хранит только этот выбор, а не сами записи. Если выбранная модель или поле больше не существует, инспектор называет их, а секция показывает ошибку вместо пустого списка.

Website с обычной публичной моделью project (поля name текст, photo медиа, intro форматированный текст, completed_on дата) может показать свои новейшие проекты так:

Выбор Значение
Коллекция project
Поле заголовка name
Поле изображения photo
Поле описания intro
Поле даты completed_on
Сколько 3

Проекты создаются, проверяются и публикуются в разделе Контент, как записи любой другой модели. Ничего в модели project не меняется.

Генерация всего сайта записывает Website или Blog, а для блога — отсортированный список его языков, в идентичность исходников генерации и манифест сайта. Добавление, удаление или изменение языка блога меняет публичные маршруты /blog, поэтому развёрнутый исходный код считается устаревшим, пока его не сгенерируют заново. Изменение порядка тех же языков ничего не меняет.

npm run backend:generate -- --model post — это не экспорт блога. Генерация одной модели выдаёт только API этой модели: без страниц сайта, без маршрутов /blog и без фронтенда блога. Генерируйте весь сайт.

При запросе страницы блога или страницы с секцией Последние записи сгенерированный сайт читает опубликованные посты из /v1 на своём хосте. Списки Последние записи в общей секции, показанной в области Site Chrome, читаются при генерации и закрепляются в сайте, поэтому не требуют формировать страницу заново при каждом запросе. Для этого Worker сайта нужен флаг совместимости global_fetch_strictly_public. Новые проекты получают его в apps/site/wrangler.jsonc. Этот файл принадлежит вам, как только он существует: Dee Wan никогда его не переписывает. Если в вашем файле флага нет, генерация и развёртывание отклоняются с public_fetch_compatibility_flag_required и называют флаг, который нужно добавить. См. отделение и проверка автономного сайта.

Встроенный управляемый шаблон и сгенерированный сайт рисуют «Последние записи» и отдают RSS-ленты. Сайт-блог не готов к рендеру, пока настройка не завершена, модель post отсутствует или изменена так, что блог не может её отрисовать (включая поле categories, tags или authors, которое не является связью дополнения), или маршрут блога конфликтует.

Определите или расширьте свои типы контента в разделе модели и поля.


Стабильная версия ещё не выпущена (pre-MVP)
Коммит исходного кода: fe23db481c422b40e317b92fc98116b4c0c26a87 (с локальными изменениями)
Дата сборки (UTC): 2026-10-18T09:22:34.630Z
Коммит для обновления: не определён: в рабочей копии есть изменения. Примечания к выпуску