Справочник9 сентября 2026 г.·обновлено 9 сентября 2026 г.

Notion как источник данных для сайта

База Notion отдаёт свойства страниц и дерево блоков через API, сайт забирает их на сборке и превращает в статические страницы. Разбор конвейера, подводных камней с истекающими ссылками на картинки и лимитом запросов.

Что это решает

Тексты правят не разработчики. Маркетолог хочет поменять заголовок на лендинге, юрист — абзац в оферте, продакт — описание тарифа, и каждая такая правка превращается в задачу, коммит и выкладку. Ставить полноценную CMS ради десятка страниц дорого: её надо развернуть, обновлять, закрывать от взлома и учить людей ей пользоваться. Notion решает это тем, что уже стоит: редактор знаком команде, права настроены, база с полями работает как список материалов, а API отдаёт содержимое наружу. Сайт при этом остаётся статическим и быстрым.

Как устроено

Доступ выдаётся через интеграцию. В настройках рабочего пространства создаётся внутренняя интеграция, она получает секретный токен, после чего нужную страницу или базу отдельно расшаривают этой интеграции. Пропущенный шаг с расшариванием — самая частая причина ответа «объект не найден» при верном токене: интеграция видит только то, что ей явно передали.

Каждый запрос уходит с двумя заголовками — авторизацией и версией API. Версия фиксируется явно и меняется только осознанно, потому что формат ответа между версиями отличается.

Дальше конвейер состоит из четырёх частей.

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

Тело страницы. Свойства и содержимое живут отдельно. Текст страницы забирается запросом дочерних блоков, и это дерево: у блока может быть признак наличия детей, за которыми нужен ещё один запрос. Вложенные списки, тогглы, колонки, элементы внутри callout — всё это уровни рекурсии. На длинной статье число запросов исчисляется десятками.

Конвертация. Блок описывается типом (paragraph, heading_2, bulleted_list_item, code, image, table) и массивом фрагментов форматированного текста. У каждого фрагмента свои пометки: жирный, курсив, моноширинный, зачёркнутый, цвет, ссылка. Задача парсера — собрать из этого markdown или сразу HTML. Готовые конвертеры покрывают частые типы блоков; редкие приходится дописывать самому, и неизвестный тип должен попадать в лог, а не молча исчезать со страницы.

Файлы. Изображения и вложения отдаются подписанными ссылками с коротким сроком жизни. Вставить такую ссылку в HTML и забыть — гарантированные битые картинки через несколько часов. Файл скачивается на сборке, кладётся в собственное хранилище или в каталог статики, и в разметку идёт уже свой адрес.

Всё, что приходит из Notion, надо забирать на сборке и складывать у себя — включая картинки.

Сборка выглядит так: скрипт ходит в API, складывает результат в JSON-кэш внутри репозитория, генератор статики строит из этого кэша страницы. Кэш в репозитории даёт две вещи сразу — повторяемость сборки (одинаковый вход даёт одинаковый выход, даже когда API недоступно) и видимый diff, по которому понятно, что именно поменялось в контенте перед выкладкой. Пересборка запускается по расписанию, по кнопке или автоматизацией из самой базы, которая дёргает вебхук деплоя.

Полезные сценарии

  • Блог или справочник, который ведут маркетологи и поддержка: новая запись в базе превращается в страницу сайта после пересборки.
  • Лендинг с текстами и ценами, меняющимися чаще кода: строки лежат свойствами страницы, вёрстка — в репозитории.
  • Список вакансий, состав команды, FAQ — короткие структурированные разделы, где нужны поля, а не свободный текст.
  • Документация продукта, которую всё равно пишут в Notion: публичная версия собирается из той же базы, что и внутренняя, по фильтру статуса.
  • Небольшой каталог с картинками и характеристиками, где количество позиций измеряется сотнями, а не десятками тысяч.

Ограничения

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

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

Отдавать страницу из Notion в момент запроса пользователя нельзя. Лимит и задержка API это не выдержат — между сайтом и Notion всегда стоит кэш или статическая сборка.

Черновиков и превью в привычном виде нет. Автор видит свою страницу в Notion, но не видит, как она выглядит на сайте, пока не пройдёт сборка. Отдельный режим предпросмотра, который тянет одну страницу по идентификатору в обход кэша, приходится делать самому.

Часть блоков конвертируется плохо. Колонки, синхронизированные блоки, вложенные базы, встроенные виджеты, сложные таблицы в вёрстке сайта выглядят не так, как в Notion. Набор допустимых блоков лучше ограничить явно и договориться о нём с авторами заранее.

Вычисляемые свойства — формулы и сводки по связям — приходят готовыми значениями и только на чтение. Записать что-то обратно в Notion со стороны сайта можно, но использовать базу как двустороннее хранилище счётчиков просмотров или лайков не стоит: лимит запросов и отсутствие транзакций сделают своё.

Версионирования контента, привязанного к релизу сайта, нет. История правок живёт в Notion и по своим правилам; откатить сайт к состоянию контента двухнедельной давности можно только через закоммиченный кэш.

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

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

Как проверить результат

Сборка с нуля на пустом кэше — базовая проверка. Она обязана проходить без ошибок и укладываться в приемлемое время, а её длительность стоит записать: рост в разы означает, что рекурсия по блокам вышла из-под контроля или добавились повторы из-за лимита.

После сборки — поиск чужих доменов в собранной статике. Ни одной ссылки на файловое хранилище Notion в готовом HTML остаться не должно; если находится хотя бы одна, картинки на сайте умрут в ближайшие часы. Проверять достаточно обычным grep по каталогу сборки.

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

Diff кэша перед выкладкой показывает, что реально изменилось. Правка одной опечатки, породившая изменения в сотне файлов, означает нестабильную сортировку или идентификаторы, которые генерируются заново на каждой сборке, — из-за этого пересобирается и переиндексируется весь сайт вместо одной страницы.

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

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

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

  • notion
  • cms
  • api
  • статические сайты