vegman.dev
Все статьи

Notion как база для контент-конвейера: статусы вместо переписки

2026-06-25кейс

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

Я разбирала ровно такую ситуацию: материалы приходили из нескольких источников, проходили редактуру и уезжали в разные каналы. Все это жило в переписке и регулярно терялось. Ниже - как превратить обычную базу в Notion в рабочий конвейер: где статус карточки управляет автоматикой, а человек остается точкой решения - не узким горлышком.

Зачем базе роль конвейера

Notion умеет больше, чем заметки. Внутри можно собрать базу (таблицу), где каждая строка - отдельная карточка материала со своими полями. Обычно такие базы живут как список: «вот наши тексты». Конвейер отличается от списка одним свойством: по карточке видно и что это, и где оно сейчас.

Я собрала одну базу, где каждая карточка - один материал, а колонки описывают его состояние:

  • Channel - куда материал должен уехать
  • Status - на какой стадии он прямо сейчас
  • Publish date - когда он должен выйти
  • Final Text - то, что реально уйдет в публикацию
  • Andy Notes - заметки редактора/правки
  • Risk Flags - места, которые стоит проверить внимательнее

Звучит скучно. Но именно этот набор убирает переписку: вопрос «в каком состоянии материал?» перестает быть вопросом к человеку и становится взглядом на колонку.

flowchart LR
  I["Inbox: черновик"] --> R["У редактора"]
  R --> N["Готово для человека"]
  N --> H["Решение автора"]
  H -->|"ставит Scheduled<br/>и дату"| SCH["Scheduled"]
  SCH --> PUB["Опубликовано"]
  R -.->|"одобрение редактора<br/>не публикует"| SCH
Публикацию включает один статус - не одобрение редактора и не готовность текста

Статус как единственный переключатель

Это главное решение - и главная ошибка первой версии.

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

Редакторское одобрение - это суждение о качестве текста. Это не команда «отправляй». Между «текст хороший» и «текст должен выйти сегодня в этот канал» лежит отдельное решение, которое принимает человек - и оно не выводится автоматически.

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

  • Status = Scheduled
  • Publish date уже наступила

Все. Один статус - один переключатель. Если материал не уехал, вы точно знаете, куда смотреть: в статус. Если уехал не тот - тоже.

Отдельное значение Channel под каждую площадку

Вторая мелочь того же рода. У поля Channel должно быть свое отдельное значение под каждую площадку. Когда две площадки делят один и тот же «канал», появляется риск отправить материал одной - в другую. И это тот класс ошибок, который замечают не вы, а читатели.

Соблазн понятен: площадки похожи, зачем плодить значения. Затем, что автоматика не различает «похоже» и «то же самое». Для нее одинаковое значение - это одинаковый адрес.

Роли: кто пишет, кто редактирует, кто решает

Конвейер держится на статусах и еще на том, что роли разведены и не лезут в чужие поля:

  • генерация пишет черновик
  • редактор правит текст и фиксирует вердикт
  • человек принимает решение «публикуем/когда/куда»

Главное: каждая роль меняет только свои поля. Генерация не трогает статус публикации. Редактор не назначает дату отправки. Решение о публикации не переписывает текст.

Это выглядит бюрократией ровно до первого разбора «почему это вышло». Когда у каждого поля есть один владелец, ответ находится за минуту, а не за вечер чтения истории изменений. И - что важнее - никто не может случайно «опубликовать» материал просто тем, что его отредактировал.

flowchart TB
  C["Запуск каждые 30 минут"] --> READ["Читает базу"]
  READ --> Q{"Есть Scheduled<br/>с наступившей датой?"}
  Q -->|"нет"| SIL["Пустой вывод.<br/>Никаких уведомлений"]
  Q -->|"да"| P["Публикует"]
  P --> MARK["Ставит отметку<br/>в базе"]
  P --> ERR{"Ошибка?"}
  ERR -->|"да"| ALERT["Сообщение автору,<br/>статус не меняется"]
Автоматика читает базу каждые полчаса и молчит, когда публиковать нечего

Автоматика читает, но не решает: 4 правила, которые спасают

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

  • Молчание - нормальный результат. Если публиковать нечего, скрипт не пишет ничего. «Ничего» - это отсутствие уведомления, а не сообщение «ничего нет». Разница принципиальная: если система 48 раз в сутки рапортует о безделье, вы перестаете читать ее сообщения - и пропускаете то единственное, которое было важным.
  • Ошибка не меняет статус. Если что-то сломалось на любом шаге (сеть, права, формат), карточка остается Scheduled и уедет на следующем прогоне. В противоположной версии скрипт снимает статус, отправка не проходит - и провал в базе становится неотличим от успеха. Вы узнаете об этом через неделю от читателя.
  • После успеха скрипт закрывает карточку сам. Он ставит Published и записывает ссылку на живой материал. Без этого база и реальность расходятся буквально за неделю - и дальше базе никто не верит. А конвейер, которому не верят, снова превращается в переписку.
  • У интеграций разные права. Скрипт ходит в Notion через интеграцию (служебный токен). Токен, который видит одну базу, может не видеть другую. И ошибка при этом выглядит как «страница не найдена», а не «нет доступа». Запомните симптом: «не найдено» в Notion очень часто означает «не выдан доступ».

Применить у себя

Что проверить на практике (за один вечер)

Если вы собираете такой конвейер у себя, вот последовательность, которую реально пройти за один вечер:

  • заведите базу, где строка - материал, и добавьте поля: channel, status, publish date, final text, editor notes, risk flags
  • выпишите список статусов и найдите среди них ровно один, при котором материал уходит в канал
  • сделайте отдельное значение channel под каждую площадку (проверьте, что ни одно значение не используется дважды)
  • создайте интеграцию, выдайте ей доступ именно к этой базе и убедитесь, что скрипт ее читает
  • в чтении базы используйте сразу два условия: status = scheduled и publish date <= today
  • намеренно «сломайте» отправку и убедитесь, что при ошибке статус не меняется
  • добавьте write-back после успеха: published + ссылка
  • убедитесь, что пустой результат не рождает уведомления.

Как понять, что получилось

Критерий простой - и он не про код.

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

Вторая проверка - через неделю после запуска. Возьмите несколько карточек со статусом Published и откройте записанные в них ссылки. Они должны вести на живые материалы в тех каналах, которые указаны в карточках. Если хотя бы одна не совпала - проблема не в Notion. Проблема в том, что где-то меняется статус «не там и не тем».

И третья, самая честная: посчитайте, сколько раз за неделю кто-то спросил в чате «а это уже опубликовали?». Ноль - это и есть результат.