Как я создавал AvtoService CPT — история разработки плагина для кузовного автосервиса

Началось всё с того, что клиенту — кузовному цеху — понадобился сайт. Услуги, портфолио с фотографиями «до/после», статьи, отзывы, калькулятор. Стандартный набор. Я взял WordPress, установил несколько плагинов, настроил тему… и понял, что поддерживать этот зоопарк — ад.

Пять разных плагинов для CPT, два для SEO, один для форм, ещё один для шорткодов. Каждый со своими настройками, конфликтами стилей и непредсказуемым поведением при обновлении. Когда клиент попросил добавить поле «Время чтения» к статьям, а потом выяснилось, что плагин для CPT не дружит с плагином для SEO — я психанул и сел писать своё.

Принцип: всего один плагин

Первое правило, которое я для себя определил: один плагин заменяет все. Никаких «установите A, B и C, чтобы заработало». Активировал — и все CPT, поля, SEO, шорткоды уже на месте.

Второе правило: никакого кода в теме. Плагин не должен требовать правок functions.php. Он сам инжектит соцсети в хедер, контакты в футер, CSS-переменные в :root. Тема может быть любой — хоть стандартная Twenty Twenty-Four, хоть самописная.

Третье правило: при отключении сайт не падает. Для этого я сделал MU-плагин с полифиллами — заглушками для всех хелперов. Если клиент решит удалить AvtoService CPT, его сайт останется рабочим, просто без кастомных блоков.

Архитектура: модули, а не монолит

Плагин вырос до 15+ файлов в includes/. Каждый модуль вешает свои хуки самостоятельно, без централизованной функции-инициализатора. Это даёт гибкость: можно отключить ненужный модуль, просто убрав require из core.php, и ничего не сломается.

// core.php — просто список подключений
require_once 'config.php';
require_once 'post-types.php';
require_once 'fields.php';
require_once 'templates.php';
require_once 'seo.php';
// ...

Никаких add_action('init', 'avtoservice_cpt_init'), внутри которых вызывается ещё десяток функций. Хуки вешаются прямо в файлах модулей — линейно, предсказуемо, без вложенности.

SEO без компромиссов

Стандартные SEO-плагины либо не видят мета-поля кастомных типов, либо требуют танцев с бубном. Я сделал свой SEO-модуль, который:

  • Выводит метабокс с полями Title, Description, Keywords, OG Image для **всех** типов записей — CPT, страниц, постов
  • Формирует OG-теги автоматически: заголовок из SEO Title, изображение из поля OG Image или из миниатюры
  • Поддерживает SEO для архивов CPT и виртуальных страниц
  • Не дублирует <title> — переопределяет стандартный через фильтр document_title_parts

Отдельная гордость — виртуальные страницы. /about/, /contacts/, /calc/, /price/ — всё это работает без единой записи в БД, через rewrite rules и template_include. И для каждой можно задать свои SEO-настройки.

Настройки в одном месте

Раньше у клиента телефоны хранились в настройках темы, соцсети — в одном плагине, реквизиты — в другом, цвета — в кастомайзере. Я собрал всё в одну страницу: Настройки → AvtoService CPT.

Шесть вкладок на JavaScript, одна кнопка «Сохранить», все опции в wp_options с autoload = yes. Никакой мороки с перезагрузкой страницы при переключении вкладок.

Дизайн шаблонов: три итерации

Первая версия шаблона услуги была типичной: фоновое фото на всю ширину с затемнением, заголовок поверх, крошки, цена. Работало, но выглядело дёшево.

Вторая итерация — строгий корпоративный стиль. Чёрно-белая гамма, сухая типографика, никаких украшений. Клиент сказал: «Слишком сухо, у нас логотип красный».

Третья версия — «Премиум-сервис». Крупный заголовок, красные акценты, параметры в отдельной полосе под героем, чеклист с зелёными галочками, сайдбар с CTA. Заработало.

С портфолио было сложнее. Я перебрал четыре схемы: «журнальный разворот», «hero-карточка», «горизонтальная лента», «строгий паспорт». Остановились на «ленте»: фото во всю ширину, заголовок с параметрами сверху, миниатюры снизу. Чисто, линейно, глаз не прыгает.

Что получилось в итоге

Один плагин, который закрывает 90% потребностей кузовного автосервиса в сайте. Без зоопарка из сторонних решений, без привязки к теме, без падения при отключении.

Клиент доволен — сайт работает, заявки идут. Я доволен — код чище, чем после первой итерации. А самое приятное — плагин можно продать следующему такому же сервису, просто поменяв цвета и контент.