Все проекты

Управление контентом

pacod-cms

Один стек — много редакционных сайтов. Статьи, реклама и статистика со встроенным AI-переводом.

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

  • Apache-2.0
  • Версия 0.0.1
  • Предварительная

Возможности

  • Редакционное ядро

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

  • Мультисайтовость изначально

    У каждого сайта своя база данных MongoDB, файлы и кэш, и он отвечает на тех хостах, которые за ним закреплены.

  • Реклама

    Размещение рекламы с конструктором HTML5-баннеров, а также страница link-in-bio для профилей в соцсетях.

  • Статистика

    Статистика по читателям, рекламе и краулерам, чтобы редакторы видели, что читают и что индексируют.

  • Многоязычность

    Контент на многих языках с настраиваемым языком оригинала; сама студия — на английском, болгарском, немецком и русском.

  • AI-перевод

    Переводите статью или целый сайт в виде задачи; любой ответ отклоняется, если в нём не сохранена в точности разметка статьи.

  • Организации и роли

    Организации, сайты и приглашения, с ролями на уровне организации и сайта, которые хранятся в pacod-id.

  • Настраиваемые PDF

    PDF статей в виде фоновой задачи, в печатном оформлении сайта или в научном формате в две колонки, с аннотацией и ключевыми словами из статьи или написанными AI.

  • Выпуски журнала

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

Место в экосистеме

Люди и сервисыLLM-провайдерыAPpacod-apCMpacod-cmsKBpacod-kbGWpacod-gwIDpacod-id
Люди и сервисыLLM-провайдерыAPpacod-apCMpacod-cmsKBpacod-kbGWpacod-gwIDpacod-id
Схема: как связаны проекты pacod Вызовы LLM Нажмите на проект, чтобы увидеть, с чем он связан.

Один стек, множество сайтов

pacod-cms обслуживает множество сайтов множества организаций из одного стека. У каждого сайта своя база данных MongoDB, своя папка с файлами и свои записи в кэше, и он отвечает на тех хостах, которые за ним закреплены. Любой зарегистрировавшийся может создать организацию, стать её администратором, создавать в ней сайты и приглашать людей для работы над ними; лимиты задаёт администратор платформы.

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

Как устроены части

Часть Что делает
pacod-cms-core Библиотека: документы, сервисы, мультиарендность, управляющий слой, начальное содержимое, модель дизайна и порт движка правил pacod-id на Java.
pacod-cms-site Публичный сайт сразу для всех сайтов: страницы, JSON только для чтения под /web/v1/**, медиафайлы, счётчики трафика.
pacod-cms-studio Студия: портал для организаций, сайтов и участников, экраны редактирования, фоновые задачи, AI.
Caddy Входная дверь, маршрутизирует по хосту: хост студии — в студию, хост pacod-id — в pacod-id, любой другой хост — на сайт.
Gotenberg Создаёт PDF статей и выпусков журнала из версий сайта для печати.

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

От хоста до страницы

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

  1. Caddy передаёт запрос сайту. В продакшене Caddy запрашивает сертификат сайта при первом посещении, но только после того, как сайт подтвердит, что хост принадлежит активному сайту.
  2. Сайт ищет хост в управляющем слое раньше, чем выполняется что-либо ещё. Хост, который не закреплён ни за одним активным сайтом, получает простой 404, а не сайт по умолчанию.
  3. Когда сайт привязан, каждая операция с MongoDB идёт в базу данных этого сайта. Если сайт не привязан, слой доступа к данным выбрасывает ошибку, а не угадывает.
  4. Макет типа страницы — области с упорядоченными секциями — разрешается относительно набора шаблонов сайта, а данные каждой секции загружаются заранее. Шаблоны никогда не делают запросов; секция, данные которой не загрузились, пропускается и записывается в лог, а страница всё равно отображается.

В студии сайт определяется по пути (/sites/<id>/mgmt/…); фоновая работа привязывает тот сайт, для которого выполняется.

Где хранятся данные

Где Что
pacod_cms Управляющий слой: организации, сайты, домены, настройки платформы, очередь задач.
site_<id> Отдельная база данных для каждого сайта: статьи, страницы, изображения, баннеры, меню, настройки, макеты, тема, статистика.
sites/<id>/ Файлы сайта: изображения к статьям, рекламные креативы, PDF. PDF черновика выпуска лежат в закрытой папке, которую отдаёт только студия.
pacod-id Люди, сессии и назначенные роли. CMS не хранит учётных записей.

Идентичность сайта — название, логотипы, контактные данные, идентификаторы сторонних сервисов — это данные, а не разметка. Сторонний идентификатор выводится, только если он задан и имеет формат своего поставщика, поэтому новый сайт не загружает никакого отслеживания. Исходный язык содержимого сайта — последний запасной вариант при отсутствии перевода и юридически определяющий текст.

Дизайн без кода

В разделе Дизайн студии каждый сайт выбирает набор шаблонов — editorial, журнал с колонкой рядом с содержимым, или minimal, одна спокойная колонка — и составляет макет для каждого типа страницы: главная, статья, рубрика, последние, постоянная страница и поиск. Среди секций — списки статей (последние, из рубрики или самые читаемые), форматированный текст, призыв к действию, поле поиска и ссылки на соцсети. Тема задаёт цвета со значениями для ночного режима, шрифты и ширины.

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

Новый набор шаблонов — это код, который устанавливает оператор, а не загружаемый файл: шаблон Thymeleaf может всё, что может сам сайт.

PDF и выпуски журнала

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

  • Два формата. Стандартный — это версия сайта для печати. Научный — макет научной статьи: шапка на всю ширину с заголовком, авторами, аннотацией и ключевыми словами, затем текст в две колонки.
  • Два способа создания. Только код берёт аннотацию и ключевые слова из описания и тегов статьи. С AI поручает pacod-gw написать аннотацию, ключевые слова и короткий колонтитул для каждой статьи и каждого языка. Текст статьи никогда не меняется.
  • Настройки PDF хранят значения по умолчанию для каждого сайта: формат и способ, бумагу (A4, Letter или A5) и поля, название журнала на каждом языке и его ISSN, колонтитул и номера страниц. Любой запуск может выбрать другой формат и способ.

Выпуск журнала собирает статьи в один PDF на каждый язык. У него есть том, номер и месяц, заголовок и редакционная статья на каждом языке и, по желанию, изображение для обложки; статьи выбираются по одной или подбираются по его месяцу, а затем упорядочиваются. При генерации создаются обложка, редакционная статья, содержание с номерами страниц, а затем статьи, с закладкой для каждой статьи и сквозной нумерацией страниц. PDF черновика выпуска скачиваются только из студии. После публикации выпуск и его PDF появляются на сайте по адресу /issues и в карте сайта.

Модель безопасности

Кто что может

Учётные записи и роли принадлежат pacod-id. Токены не несут ролей: студия следит за потоком назначенных ролей pacod-id и сама решает каждое разрешение по манифесту CMS (authz/cms.yaml). Роли таковы: администратор платформы, провижнер, администратор организации, администратор сайта, дизайнер, редактор, автор и аналитик — на уровне платформы, организации или сайта. Автор пишет; редактор ещё и публикует.

  • Каждый обработчик студии объявляет нужное ему разрешение; обработчик, который ничего не объявил, отклоняется. Неявных ролей нет.
  • Если поток pacod-id не отвечал минуту, студия отвечает 503, а не принимает решение по ролям, которые, возможно, уже отозваны. Публичные сайты это не затрагивает.

Сайты изолированы друг от друга

  • Студия находится на другом регистрируемом домене, чем сайты, иначе она не запускается. В противном случае скрипт сайта мог бы устанавливать cookie для студии и обойти её защиту от CSRF.
  • Студия никогда не отдаёт HTML или скрипты сайта. Предпросмотр черновиков и HTML5-баннеров встраивается с собственного origin сайта.
  • Gotenberg изолирован: он может обращаться только к внутреннему адресу сайта и не выполняет JavaScript.
  • До читателя доходят только опубликованные статьи — на каждом маршруте, в каждом списке, ленте, карте сайта и PDF. Черновик выпуска журнала никогда не бывает публичным.

AI, который не трогает ваши ключи

Каждый вызов AI проходит через pacod-gw; студия никогда не хранит ключ поставщика. Для новых организаций AI по умолчанию выключен: администратор платформы включает его для организации, а администратор сайта может отключить его для своего сайта.

  • Перевод статей выполняется как задача. Переведённый текст должен в точности сохранить разметку оригинала — меняться могут только alt, title, aria-label и placeholder, — иначе он отклоняется.
  • Перевод сайта охватывает постоянные страницы, названия разделов, меню, страницу ссылок и, если отмечено, теги, не перезаписывая правки, сделанные во время выполнения; не более 2000 вызовов за запуск.
  • Помощь в написании переформулирует выделенный текст шестью способами и предлагает анонс и теги.
  • Альтернативный текст на каждом языке предлагает модель компьютерного зрения по самому изображению.
  • Помощник по дизайну набрасывает тему или макет по нескольким словам и записывает только в черновик.
  • Шапка PDF: для PDF, созданных с AI, аннотация, ключевые слова и колонтитул для каждой статьи и каждого языка, проверенные как обычный текст. Они используются повторно, пока статью не отредактируют.

Шлюз видит только непрозрачные идентификаторы, никогда не имена и не адреса электронной почты.

Три окружения, один Makefile

dev stage prod
Входная дверь HTTP, плюс HTTPS от локального CA Caddy HTTPS (Let's Encrypt) HTTPS (Let's Encrypt)
Почта pacod-id перехватывает mailpit перехватывает mailpit ваш релей
AI мок-шлюз мок-шлюз ваш pacod-gw или выключен
Демонстрационные сайты да да нет

Stage — это конфигурация продакшена с перехваченной почтой и имитацией AI. make check не даёт запуститься, пока не хватает секрета или конфигурация небезопасна. Делайте резервные копии .env, баз данных MongoDB, файлов сайтов и PostgreSQL pacod-id. /mgmt-health студии проверяет только, что она жива: студия, которая не может достучаться до pacod-id, остаётся «здоровой», пока её экраны отвечают 503, и сообщает об этом в своём логе.

Каждое окружение работает в pacod-net, Docker-сети, общей для всех проектов pacod. Собственные сервисы CMS — сайт, студия, MongoDB и Gotenberg — описаны в одном compose-файле; её собственные копии общих компонентов — Caddy, pacod-id со своим PostgreSQL, шлюз для разработки и перехватчик почты — во втором, который Makefile загружает вместе с первым. На одной машине помещается только один стек с общими компонентами. pacod-demo загружает только первый файл и запускает CMS вместе с остальными проектами за одним Caddy, одним pacod-id, одним PostgreSQL и одним шлюзом; он доступен по адресу demo.pacod.io.

Ограничения и что почитать

Известные ограничения v1:

  • У идентичности сайта (siteSettings) пока нет экрана в студии; она редактируется в базе данных.
  • Демонстрационное содержимое есть только на английском.
  • Список участников не показывает роли уровня платформы.

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

В репозитории:

Скриншоты

Технологии

Языки
  • Java
Технологии
  • Java 25
  • Spring Boot 4.1
  • Thymeleaf
  • MongoDB
  • Maven
  • Caddy
  • Gotenberg
  • Docker

Быстрый старт

Машина разработчика
make initmake upopen http://studio.localhost:8000/
Ещё один сайт из командной строки
make site-create SLUG=acme NAME="Acme News" HOSTS=acme.localhost DEMO=1

Работает с

  • pacod-id

    Студия выполняет вход пользователей через pacod-id, где также хранятся их роли на уровне организации и сайта.

  • pacod-gw

    AI-функции работают через шлюз — студия никогда не хранит ключ провайдера.

Лицензия

Apache-2.0

Собственный код проекта распространяется под Apache-2.0. Студия включает редактор TinyMCE (GPL-2.0-or-later), поэтому собранная студия в целом распространяется на условиях GPL-3.0. Публичный сайт его не содержит.