GRADE — раздел «Полезные статьи» (блог) для grade.law
Юридическое бюро (налоговые/уголовные споры, банкротство, защита бизнеса) · Юридические услуги (налоговые споры, защита бизнеса, банкротство, сопровождение проверок ФНС/МВД)
Экспертиза адвокатского бюро лежала в 42 файлах, которых никто не видел. Собрал из них работающий раздел сайта, открытый поиску.
- PHP
- MODX Revolution
- pdoTools
- Fenom
- FormIt
- MySQL
- JavaScript
- jQuery
- Swiper
- HTML
- CSS/SCSS
- Python
- JSON-LD
- Apache
- nginx
В цифрах
- 42
- статьи мигрированы из PDF в ресурсы MODX (ФНС 12 / МВД 10 / налог.оптимизация 8 / банкротство 6 / арбитраж 3 / защита 3)
- 6
- категорий блога (контейнеры-ресурсы + отдельные страницы-категории под SEO)
- 3 / 9 / 7
- новых шаблона / чанков (blog_*) / TV (art_*, seo_*, og_image) созданы в MODX
- 11
- идемпотентных PHP-скриптов сборки через MODX API (01_create_tvs … 11_integrate)
- 3
- research-досье по стеку (stack-research + blog-pdotools-seo ~1057 стр. + blog-forms-images-frontend ~1015 стр.)
- 77 таблиц / 71 ресурс
- объём БД и контента сайта, охваченный read-only аудитом (Фаза 2)
- QA пройден заказчиком
- формы, мобильная вёрстка, пункт меню проверены лично заказчиком; раздел запущен на проде
Ключевое
- Каждая из шести практик — отдельная страница со своим адресом: человек попадает из поиска сразу в нужную тему, а не на общий список.
- Написал конвейер переноса: программа разбирает файлы разного формата, определяя заголовки по размеру шрифта, а списки — по расположению маркеров.
- Собирал раздел скриптами, которые можно запускать повторно: на живом сайте без тестовой копии это единственный способ не потерять сделанное при ошибке.
- Закрыл поисковый пробел: у страниц не было ни собственных заголовков для выдачи, ни описаний, ни разметки — теперь есть.
- Заказчик лично проверил формы, поведение на телефоне и меню и принял работу; раздел запущен.
Задача
Адвокатское бюро ведёт налоговые споры, банкротства и защиту бизнеса при проверках. Экспертиза у бюро была и была записана: 42 материала лежали отдельными файлами, которые не видел никто, кроме сотрудников. На сайте не существовало раздела, где эти тексты работали бы на привлечение клиентов.
Мешало и другое: сайт был почти невидим для поиска на уровне отдельных страниц. У них не было ни собственных заголовков для поисковой выдачи, ни описаний, ни разметки, по которой поисковик понимает, что перед ним экспертная статья юриста, а не случайный текст.
Что сделано
- Начал с разбора существующего сайта, ничего в нём не меняя: как устроен, что можно переиспользовать, где риски. Сайт работает на устаревшей версии движка, обновлять которую заказчик не планирует, — все решения подбирались под неё, а не под актуальные версии.
- Спроектировал раздел так, чтобы каждая из шести практик была отдельной страницей с собственным адресом. Человек из поиска попадает сразу в нужную тему, а не на общий список, откуда ещё надо искать.
- Написал конвейер переноса: 42 файла разного оформления разбирает программа, которая определяет заголовки по размеру шрифта, а пункты списков — по расположению маркеров на странице. Простое извлечение текста здесь не годилось: структура терялась, и статьи превращались в сплошное полотно.
- Собирал раздел скриптами, которые можно запускать повторно. Все элементы создавались скрытыми и включились одним движением, когда раздел был готов целиком, — на живом сайте без тестовой копии иначе нельзя.
- Закрыл поисковый пробел: у статей появились собственные заголовки и описания для выдачи, разметка «статья — юрист — раздел», карточки для соцсетей и хлебные крошки.
Итог
Раздел «Полезные статьи» работает на сайте бюро: 42 материала в шести практиках — от споров с налоговой до банкротства. Заказчик лично проверил формы, поведение на телефоне и пункт меню и принял работу.
Тексты, которые до этого лежали файлами и не приносили ничего, теперь открываются из поиска, каждый по своему адресу и со своей карточкой в выдаче.
Технические детали
Решение и подход
- Архитектура блога — на чистом pdoTools, без сторонних движков (Articles/Tickets/Collections под 2.8.1 несовместимы — подтверждено исследованием). Категории — контейнерами в дереве (Вариант A), что даёт чистые ЧПУ
/poleznye-stati/<категория>/<статья>/и сильную SEO-страницу под прямые заходы. - Шаблон статьи построен на схеме существующего шаблона «Услуга» (id 5) + добавлены хлебные крошки (pdoCrumbs, 4 уровня), лид с буквицей, sticky-сайдбар (7 услуг + карточка автора + мини-CTA), тёмный CTA-баннер с формой.
- Каталог — серверный вывод категорий/статей (pdoResources) + JS-аккордеон с deep-link
?cat=и активной первой непустой категорией. - Авторы — через listbox-TV на базе существующего механизма карточек
user1…user8(а не MIGX 3.0.0-alpha5: alpha-баг подтверждён исследованием). Это сознательный компромисс относительно плана (где предлагались авторы-ресурсы) — по решению заказчика. - Сборка — идемпотентные PHP-скрипты через MODX API (
_bootstrap.php+01…11), запускаемые фиксированным/opt/php73/bin/php(дефолтный PHP 8.3 не поднимает MODX 2.8.1). Все элементы создаются скрытыми, затем включаются «точкой интеграции». - Стили изолированы в
blog.css— основнойstyle.css(~80 КБ) не трогается; шрифты SF Pro Text, иконкиgrade-icon, Swiper переиспользованы.
Стек и обоснование
- MODX Revolution 2.8.1 + pdoTools 2.12.7 / Fenom — платформа существующего сайта; решения принимались строго под эти версии (не под MODX 3 / pdoTools 3).
- PHP 7.3.33 — версия прода (зафиксирована через ISPmanager); под неё писались код и скрипты; обновление вне scope (зафиксировано как риск).
- MySQL 8.0 / MyISAM — существующая конфигурация; учтены особенности (sql_mode, коллации, отсутствие транзакций).
- Python (PyMuPDF, Pillow) — для извлечения структуры из PDF и генерации OG-обложек: разбор уровней по размеру шрифта и списков по координатам маркеров оказался надёжнее «плоского» pdftotext.
- JS (jQuery + Swiper) — стек сайта; аккордеон и галерея сделаны без новых зависимостей.
- Формы — переиспользован существующий паттерн
form-handler.js→assets/php/submit.php(Telegram + SMTP) со скрытымformId, чтобы не плодить вторую механику.
Инженерные вызовы
- Работа напрямую на боевом сайте без стейджинга — компенсирована множественными бэкапами/точками отката, созданием всех элементов «скрытыми» и единой «точкой интеграции».
- Контент только в БД (MODX) — потребовал сборки через MODX API-скрипты, а не правки файлов; отдельная ловушка с правами кэша (скрипты от root создают кэш
root:root→ Apache ломается; решение —chownкэша после каждого build). - Неоднородные PDF — единый парсер структуры (PyMuPDF) с распознаванием заголовков по размеру шрифта и склейкой 2-строчных пунктов списков; баг склейки выявлен и исправлен, 42 статьи перемигрированы.
- Legacy-ограничения и риски: MODX 2.8.1 с незакрываемым без обновления RCE (CVE-2022-26149), EOL PHP 7.3, alpha-MIGX, отсутствие сборки фронта — обойдены конфигурацией/изоляцией; критичное вынесено заказчику.
- Безопасность секретов: в проде обнаружены захардкоженные секреты (Telegram-токен/chat_id, SMTP-пароль в
submit.php, пароль БД в конфиге). Их значения не извлекались и не выносились в артефакты — зафиксирован только факт и рекомендация ротации/выноса (выполняет разработчик заказчика).
Услуги в проекте
- разработка
- доработка существующего
- аудит
- миграция
- SEO
- деплой
- контент