Два прозореца на редактора на статии на pacod-cms, светъл и тъмен, един върху друг, всеки отворен на статията на Starward Forty-eight hours on Halcyon Station, с панелите за публикуване и автори до текста.
Редакторът на статии в студиото през деня и през нощта: текстът, а до него състоянието, датата, авторите и разделите на статията. Самото студио е на английски, български, немски и руски.

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

Управление на съдържание

Възможности

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

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

Мултисайт по замисъл

Всеки сайт има собствена MongoDB база данни, файлове и кеш и отговаря на хостовете, които заявява.

Реклама и статистика

Рекламни резервации с конструктор на HTML5 банери, link-in-bio страница за профили в социалните мрежи и статистика за читатели, реклама и обхождащи ботове, така че редакторите виждат какво се чете и какво се обхожда. Резервации за отделни раздели и икона на GitHub за страницата с връзки предстоят (още не е издадено, в клона blog-site).

Многоезичност

Съдържание на много езици с конфигурируем оригинален език и AI превод на статия или цял сайт като задача, като всеки отговор се отхвърля, ако не запазва точно маркирането на статията; самото студио е на английски, български, немски и руски. Руски език за собствените надписи на публичния сайт предстои (още не е издадено, в клона blog-site).

AI помощ при писане

Заглавия, цяла статия по кратко задание, пасаж на мястото на курсора и текст, оформен в стилизирани блокове, без да се губи нито дума на автора.

AI дизайн

Тема, оформление на страница или дизайнът на целия сайт, изготвени по няколко думи чрез доработка на текущата чернова; само чернови, с една отмяна.

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

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

PDF файлове и броеве на списание

PDF файлове на статиите като фонова задача, в оформлението за печат на сайта или в научен формат на две колони, с резюме и ключови думи, взети от статията или написани от AI; брой на списание събира статии в по един PDF за всеки език с корица, уводна статия, съдържание и номерирани страници и се публикува в архива на сайта.

Експорт и възстановяване

Сайт или цяла организация се изтегля като един ZIP и се възстановява като нов, в тази инсталация или в друга.

Диаграмата на платформата с осветен pacod-cms и приглушени останали проекти: линия от хората към pacod-cms, зелена пунктирна връзка към pacod-gw и нататък към моделите и златиста пунктирна връзка към pacod-id.
Мястото на pacod-cms. Хората използват студиото и сайтовете му (сиво). AI функциите на студиото стигат до модел само през pacod-gw (зелени точки), а студиото вписва хората през pacod-id (златисти точки); читателите на сайтовете не се вписват никъде. pacod-demo го пуска заедно с другите проекти.

Екранни снимки

Началната страница на Starward в прозорец на браузър: заглавна лента със седем раздела и поле за търсене, водещият материал Why the stars do not twinkle in space върху звездно поле със зелена мъглявина и реклама на Aurelian Lines отдолу.
Starward, демо сайтът на набора шаблони magazine: водещ материал на цялата ширина върху снимка на NASA, а под него HTML5 банер на един от измислените му рекламодатели.
Екранът „Websites“ на pacod-cms със списък от Demo Journal, Demo Notes и Starward в една демо организация, всеки с адрес, език en и активно състояние, с бутони за нов сайт и за възстановяване на сайт.
Една инсталация, много сайтове: списъкът със сайтове в студиото, всеки с организацията, адресите, езика на съдържанието и състоянието си. Всеки има своя база данни, папка с файлове и записи в кеша.
Екранът „Дизайн“ на pacod-cms за Starward: наборът шаблони Magazine с описанието му, таблица с шест типа страници от началната до търсенето, всяка отбелязана като собствена на сайта с бутон Edit, и темата с 26 зададени стойности.
Екранът „Дизайн“: наборът шаблони на сайта, оформление за всеки от шестте му типа страници и темата му, всичко променено в студиото, без да се пипа код.
Тъмният екран на темата в pacod-cms за Starward с два готови варианта, Nightfall и Newsprint, над таблица с цветове като страница, карти, линии, текст и акцент, всеки с шестнадесетична стойност за деня и за нощта, и бутони Preview и Publish.
Редакторът на темата през нощта: започвате от готов вариант на набора, Nightfall или Newsprint, после давате на всеки цвят стойност за деня и за нощта. Променливите са общи за всички набори шаблони, така че темата оцелява при смяна.
Екранът за реклама на pacod-cms за Starward със списък от шест активни резервации за Aurelian Lines, Kestrel & Vane, Rimstone Lodge, Nightglass Tours и Lumen Assurance, в страничната колона или отгоре, всяка със страниците и броячите си.
Екранът за реклама: всяка резервация с типа, позицията, реда, страниците, на които върви, периода, показванията и кликванията си. Петимата измислени рекламодатели на Starward показват ръчно написани HTML5 банери и едно статично изображение.

Един стек, много сайтове

pacod-cms обслужва много сайтове на много организации от един стек. Всеки сайт има собствена MongoDB база данни, собствена папка с файлове и собствени записи в кеша и отговаря на хостовете, които заявява. Всеки, който се регистрира, може да създаде организация, да стане неин администратор, да създава сайтове в нея и да кани хора да работят по тях; администратор на платформата задава лимитите.

Дизайнът изхожда от това, че собственикът на един сайт може да е враждебен към всички останали в инсталацията. Сайтовете изпълняват скриптове, написани от собствениците им — HTML5 банери, таг мениджъри, текстове на статии, — и платформата трябва да държи тези скриптове и тези данни там, където им е мястото.

Как се свързват частите

Част Какво прави
pacod-cms-core Библиотека: документи, услуги, мултитенантността, контролната равнина, начално съдържание, моделът на дизайна и Java порт на механизма за правила на pacod-id.
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 не съхранява акаунти.

Идентичността на сайта — име, лога, данни за контакт, идентификатори на трети страни — е данни, а не маркировка. Идентификатор на трета страна се изобразява само когато е зададен и има формата на своя доставчик, така че нов сайт не зарежда никакво проследяване. Оригиналният език на съдържанието на сайта е последният резервен вариант при липсващ превод и юридически валидният текст. Каноничен адрес, hreflang и метаданни на статията в заглавната част (head) на всяка страница за читатели, както и Atom емисия за всеки сайт и за всяка категория, предстоят (още не е издадено, в клона blog-site).

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

В раздела Дизайн на студиото всеки сайт избира един от три набора шаблони — editorial, начална страница с решетки от статии и колона до съдържанието; minimal, една спокойна колона; или magazine, изграден около изображенията, с основна статия на цялата ширина, снимки в мозайка и статии, които се отварят със своята снимка — и подрежда оформление за всеки тип страница: начална, статия, категория, най-нови, постоянна страница и търсене. Сред секциите са списъци със статии (най-новите, от категория или най-четените), форматиран текст, призив за действие, поле за търсене и връзките към социалните мрежи; секция, която показва текста на постоянна страница на езика на читателя, предстои (още не е издадено, в клона blog-site). Темата задава цветове със стойности за нощен режим, шрифтове и ширини.

Текстът на статия може да съдържа стилизирани блокове от затворен списък: встъпителен абзац, каре с бележка, изнесен цитат, каре с основните факти, две колони и фигура с надпис — обикновена или подравнена вляво или вдясно. Сайтовете ги стилизират според темата, също и в изгледите за печат, а значи и в PDF файловете, а редакторът ги показва така, както ще ги видят читателите. Пет от тях са в менюто Блокове на редактора; AI оформлението може да използва и шестте. Примери с код, вмъквани от редактора и оцветявани с Prism в сайтовете, предстоят (още не е издадено, в клона blog-site).

Смяната на набора първо показва какво ще се загуби, и нищо не се премахва: секциите, които новият набор не може да покаже, се запазват и се връщат при обратна смяна. Оформленията и темата остават чернови, докато някой с право да ги публикува не го направи, независимо дали ги е написал човек или AI. Асистентът за дизайн изготвя тема, оформление или дизайна на целия сайт по няколко думи; подробностите са в раздела за AI по-долу. Прегледът показва черновите от собствения адрес на сайта, в ширина за компютър, таблет или телефон, чрез подписан токен, валиден 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, вместо да решава с роли, които може вече да са отнети. Публичните сайтове не са засегнати.

Сайтовете остават разделени

  • Студиото и pacod-id са на различен регистрируем домейн от сайтовете, иначе студиото отказва да стартира. В противен случай скрипт на сайт би могъл да задава бисквитки за тях и да обезсили защитата им от CSRF. Инсталация, чиито сайтове са до един доверени, например демо на един домейн, може да приеме този риск с PACOD_SITE_DOMAIN_SHARED=true: тогава студиото стартира с предупреждение, а сайт пак никога не може да заеме собствения хост на студиото или на pacod-id.
  • Студиото никога не сервира HTML или скриптове на сайт. Прегледите на чернови и на HTML5 банери се вграждат от собствения произход (origin) на сайта.
  • Gotenberg е изолиран: достига само вътрешния адрес на сайта и не изпълнява JavaScript.
  • До читателя стигат само публикувани статии — по всеки маршрут, във всеки списък, карта на сайта и PDF. Брой на списание в чернова никога не е публичен.

AI, който не пипа ключовете ви

Всяко извикване на AI минава през pacod-gw; студиото никога не държи ключ на доставчик. За нови организации AI е изключен по подразбиране: администратор на платформата го включва за всяка организация, а администраторът на сайт може да го изключи за своя сайт.

Писане

В редактора на статии помощта при писане работи с текста такъв, какъвто е в момента, запазен или не:

  • Преформулиране на избран текст по шест начина: по-ясно, по-кратко, по-подробно, коригирано, по-официално или по-приятелски.
  • Заглавия: до три заглавия за статията.
  • Чернова на цяла статия — заглавие, описание и текст — по кратко задание, къса, средна или дълга (около 300, 600 или 1200 думи), на оригиналния език на сайта. Използва само фактите от заданието; където липсва факт, пише заместител в квадратни скоби, който авторът да попълни, и никога не измисля.
  • Писане на мястото на курсора: пасаж по кратко задание, на езика и в стила на текста около него, по същото правило за фактите.
  • Оформяне на избран текст или на целия текст в заглавия, списъци, акценти и стилизираните блокове. Всяка дума на автора трябва да остане, в своя ред, иначе отговорът се отхвърля. Текст, който съдържа фрейм, видео, скрипт или формуляр, се отказва преди всяко извикване, защото оформянето би го изгубило.
  • Резюме и тагове за статията и алтернативен текст за всеки език, който модел за изображения пише въз основа на самата картина.

Отговорите се изчистват до кратък списък от тагове и схеми на връзки (http, https, mailto, относителни). Клас остава само там, където назовава стилизиран блок на собствения му елемент; без style, без скриптове, без изображение, което текстът на автора не е съдържал, и без връзка към адрес, който текстът на автора, заданието или статията не са дали. Числа, имена и изнесени цитати, които отговорът съдържа, а материалът му не, се изброяват до него, за да ги провери авторът — евристика, а не доказателство. Преформулиране, пасаж или оформяне първо се показва в преглед и се вмъква като една стъпка за отмяна; черновата попълва формуляра. Нищо не се запазва, докато авторът не запази.

Дизайн

  • Асистентът за дизайн изготвя тема или оформлението на един тип страница по няколко думи. По подразбиране доработва текущата чернова, която моделът вижда, и променя само каквото иска заданието; при поискване започва отначало. Всеки отговор се проверява така, сякаш го е въвел оператор, а едно щракване отменя промяната или я връща.
  • Дизайнът на целия сайт — темата и оформлението на всеки тип страница — се изготвя по едно задание като задача. Всяка стъпка е самостоятелна, така че неуспешна стъпка не спира останалите; задачата може безопасно да се изпълни отново, може да се откаже и записва цената си. Един сайт има най-много една задача за дизайн наведнъж.

И в двата случая се променят само чернови; за публикуването пак е нужен някой, който има право.

Превод и PDF файлове

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

Какво трябва да издържи всеки отговор

  • Всеки отговор трябва да отговаря на строга JSON схема. Отговор, който моделът е прекъснал или отказал, е неуспех и нищо от него не се записва.
  • Текстът на човека се изпраща като материал и на модела се казва, че той никога не е инструкция, дори когато звучи като такава.
  • Гейтуеят вижда само непрозрачни идентификатори, никога имена или имейл адреси.

Три среди, един 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, като JSON или текст (APP_LOG_FORMAT).

Експортът и възстановяването пренасят сайт от една инсталация в друга. Сайт или цяла организация се изтегля от студиото като един ZIP със съдържанието и файловете си, без статистиката на посещенията, членовете и хостовете. Възстановяването проверява целия архив, преди да създаде каквото и да е, и винаги създава нов сайт или нова организация, в тази инсталация или в друга; качвания до 2 GiB се приемат само по тези два пътя. Резервните копия на цялата платформа остават дъмпове на MongoDB.

Нова инсталация в dev или stage създава три демо сайта: Demo Journal (editorial), Demo Notes (minimal) и Starward (magazine) — списание за космически пътувания в измислена звездна система: 24 обемни статии, които използват всеки стилизиран блок, петима автори, свои страници, менюта, оформления, тема и два публикувани броя на списанието, 37 снимки на NASA с посочено авторство и пет измислени рекламодателя с HTML5 рекламни материали. make site-create … DEMO=space или make seed SITE=<id> DEMO=space дава на друг сайт съдържанието на Starward. Зареждане на сайт от собствена папка (SEED_DIR=<folder>), проверена изцяло, преди да се запише каквото и да е, предстои (още не е издадено, в клона blog-site).

Всяка среда работи в pacod-net, Docker мрежата, която всички проекти на pacod споделят. Входните точки, до които стигат само сървъри, като вътрешната на pacod-id, са във втора, вътрешна мрежа, pacod-admin-net, към която се присъединява студиото. Собствените услуги на CMS — сайтът, студиото, MongoDB и Gotenberg — са в един compose файл; собствените му копия на споделените части — Caddy, pacod-id с неговия PostgreSQL, гейтуеят за разработка и прихващачът на поща — са във втори, който Makefile зарежда заедно с първия. На една машина се побира само един стек, който изпълнява споделените части; работата зад Caddy и pacod-id, които вече работят на хоста (PROXY_MODE=external), предстои (още не е издадено, в клона blog-site). pacod-demo зарежда само първия файл и изпълнява CMS заедно с другите проекти зад един Caddy, един pacod-id, един PostgreSQL и един гейтуей; той е достъпен на demo.pacod.io.

Какво е тествано и къде са границите

  • Модулните тестове се изпълняват с български като оригинален език, така че се изпитва конфигурацията, различна от тази по подразбиране.
  • Интеграционните тестове пускат два сайта в една истинска MongoDB и проверяват, че остават разделени: маршрутизация, разпознаване на хоста, кешове, съхранение и статистика.
  • make e2e проверява вписването и портала на работещия стек.
  • По-новите AI заявки и отговори — картата с черновата, списъкът със заглавия, доработката и отмяната в асистента за дизайн, задачата за дизайн и списъкът с факти за проверка — още не са проверени на работещ стек.

Ограничения и още за четене

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

  • Идентичността на сайта (siteSettings) все още няма екран в студиото; редактира се в базата данни.
  • Демо съдържанието е написано на английски, затова може да го получи само сайт, чийто език на съдържанието е английски.
  • Списъкът с членове не показва роли на ниво платформа.

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

В хранилището:

Бърз старт

Машина за разработка

make init
make up
open http://studio.localhost:8000/

Още един сайт от командния ред

make site-create SLUG=acme NAME="Acme News" HOSTS=acme.localhost DEMO=1

Работи с

  • pacod-id: Студиото вписва хората през pacod-id, който съхранява и ролите им за всяка организация и за всеки сайт.
  • pacod-gw: AI функциите минават през шлюза — студиото никога не държи ключ на доставчик.
  • pacod-demo: Пуска CMS заедно с другите проекти зад един Caddy, един pacod-id и един шлюз — студиото на живо и три демо сайта.

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