Перейти к содержимому
Эльдар Шахвалиев
Обсудить проект
← Все проекты
202606.2026 — 06.2026В продеполный цикл

GRADE — раздел «Полезные статьи» (блог) для grade.law

Юридическое бюро (налоговые/уголовные споры, банкротство, защита бизнеса) · Юридические услуги (налоговые споры, защита бизнеса, банкротство, сопровождение проверок ФНС/МВД)

Fullstack/MODX-разработчик: исследование → аудит → план → реализация → миграция контента → QA

Экспертиза адвокатского бюро лежала в 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.jsassets/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
  • деплой
  • контент