Smartway — переезд корпоративного сайта с Tilda на WordPress
B2B-сервис управления командировками (travel-tech SaaS) · Travel-tech / корпоративные командировки (business travel management, B2B SaaS)
- PHP
- JavaScript
- HTML
- CSS/SCSS
- WordPress
- классическая тема (Underscores _s)
- SCF (Secure Custom Fields)
- ACF Flexible Content
- Gutenberg (ACF-блоки)
- Contact Form 7
- Flamingo
- FluentSMTP
- Yoast SEO (JSON-LD)
- Redirection
- IndexNow
- WP Super Cache
- MySQL
- Splide
- GLightbox
- intl-tel-input
- WebP/AVIF
- Apache/Nginx
- shared hosting (reg.ru)
- WP-CLI
- rsync
- Git
- Playwright
- REST API
- Composer/WPCS
- 41 → 14
- 11 → 3
- 22
- 58
- 366
- 457
- 19
- 10 → 6
- ≥2,3×
- 37 → 19 мс
- 2,23 ГБ + 127 МБ
- 10 находок (0×P0, 1×P1, 3×P2, 4×P3, 2×info)
- 31 раздел / 40 скриншотов
- 11 правок / 7 кластеров
Контекст и задача
Smartway (smartway.today) — российский B2B-сервис управления командировками: единая платформа для брони авиа/ж-д билетов, отелей и такси, согласования поездок, тревел-политик и интеграции с 1С (по данным сайта — 7600+ клиентов, 520 000+ броней в месяц). Источник: WebFetch публичной главной (2026-06-29).
Заказчику нужен был переезд корпоративного сайта с Tilda на WordPress прежде всего ради SEO-фундамента: чистый оптимизируемый код, контроль индексации (robots/sitemap/IndexNow), ЧПУ и массовые редиректы, шаблоны мета-тегов, управляемая микроразметка, Core Web Vitals и жёсткие лимиты веса страниц (источник: docs/tasks/ТЗ на разработку и верстку.md). Отдельное ТЗ на внутреннюю оптимизацию требовало QAPage на /faq, mailto/tel-ссылок, удаления keywords, хлебных крошек (источник: docs/tasks/smartway.today - ТЗ на ВО.pdf).
Исходное состояние: над сайтом уже работала предыдущая команда (в репозитории — следы хардкод-путей /Users/danikkondratenko, фронт-эталон в github.com/fauztdin0ff/smartway). Автор зашёл как новый подрядчик на доработку. Полный full-stack аудит (Фаза инициализации) выявил критичные проблемы: контент лендингов захардкожен в PHP, .wpress-бэкапы качались наружу с HTTP 200, ACF Pro был nulled, осиротевший CPT case, mu-plugin agent-bridge на статичном токене (источник: docs/progress.md §Инициализация, docs/handoff.md).
Что я сделал
Честно про характер работ: это не greenfield, а адаптация существующей темы после другой команды + значительный net-new бэкенд + аудит + миграции + DevOps + SEO (engagement: mixed). Утверждённая стратегия — «адаптировать, не пересобирать» (источник: docs/tasks/00-project-plan.md, docs/handoff.md).
Это длительный многофазный проект (журнал — docs/progress.md):
- Инициализация: full-stack аудит силами 8 параллельных аудиторов →
docs/audit/00-README.md+ 01–08; согласование стратегии и плана. - Фаза 1 — рабочий контур: git для темы,
.gitignore/.distignore, деплой-скрипт (scripts/deploy-theme.sh, rsync), WP-CLI на сервере; локальный WP/Docker сознательно не поднимали. - Фаза 2 — гигиена: плагины 41→14, миграция nulled ACF Pro → SCF (Secure Custom Fields), mu-plugins 11→3 (удаление
agent-bridgeзакрыло REST-дыру), удаление неактивной темы и мёртвого кода, хардненинг wp-config. - Фаза 3 — инфраструктура миграции + пилот: конвертер
bin/build-front.php(dist→шаблоны), общий shellheader-front/footer-front, пилотная страницаtaxi. - Фаза 4 — постраничная миграция: 22 страницы dist натянуты на тему, меню из БД (walker), формы dist 1:1 через CF7 REST (AJAX), смешанный режим со старыми ~26 страницами; PHP-lint 134 файлов — 0 ошибок.
- Фаза 5 — net-new бэкенд: блог (лента/статья/категория), оферта (CPT offer), CPT
case+ миграция D1 (19 client→case + 301), дедуп экспертов 10→6, авторизация D4 (внешний кабинет через ACF-URL + CF7-лид регистрации). - Фаза 6 — производительность + SEO: 6A (переносимый
inc/seo.php: Organization-schema, OG; noindex теста), 6B (2,23 ГБ бэкапов из вебрута, −260 ревизий), 6C/D (WebP-конвейер, 457 изображений,<img>→<picture>), 6E (WP Super Cache на mod_rewrite + preload). - Фаза 7 — QA: аудит против dist (10 находок, 0×P0) + фиксы; отчёт + 43 скриншота.
- Фаза 8 — доработки по ТЗ (8A→8E): мультиагентный аудит (4–5 параллельных субагентов: сервер/код/веб-ресёрч/Playwright) → план; 8A хардненинг (REST users-enum→404, security-заголовки в
.htaccess, деактивация 2× AI1WM); 8B редактируемость — библиотека из 58 ACF Flexible Content layout-ов на 9 лендингов + главную + auth/legal, 366 ассетов в медиатеку; 8C SEO (Person/Article/FAQPage schema, canonical/og, URL без слеша); 8D пагинация/cases/+ LCP/defer; 8E аналитика (поля GTM/GA4/Метрика — заказчик заполняет без разработчика), рольsmartway_seo, чистка. - Новая волна (11 правок / 7 кластеров): блог, шорткоды + ACF-блоки статьи, кейсы (архив + banner + poster + 2 наполненных демо), правовые (offer/UA), формы (success-экран + intl-tel-input маска), SEO (крошки/ToC). + настройка FluentSMTP, доставка CF7-заявок, пост-фиксы типографики статей, HTML-руководство админа (31 раздел, 40 скриншотов) и отчёт заказчику в дизайн-системе сайта.
Решение и подход
Архитектура темы — классическая PHP-тема на Underscores (_s), сильно кастомизированная, на SCF (источник: CLAUDE.md). Ключевые инженерные решения:
- Реестр бандлов
route → bundle(inc/page-bundles.php+inc/enqueue.php): поэкранная загрузка CSS/JS, повторяющая исходные HTML 1:1 → выполнение требования ТЗ «JS по шаблонам, не глобально» и лимитов веса. - Гибрид-контент-модель (8B-2): библиотека ACF Flexible Content layout-ов с нулём fallback (контент только в БД), медиатека-пикер вместо путей, горизонтальные табы и группировка полей в редакторе — спроектировано под контент-команду без разработчика (источник:
docs/tasks/phase8-8b2-pilot-taxi-plan.md,docs/progress.md). - SEO без костылей (8C): URL без слеша сделан через ядро (
permalink_structure+redirect_canonical, 301 одним хопом), а не кастомным редиректором; schema — через фильтры Yoastwpseo_schema_*; переносимыйinc/seo.phpпод гардWPSEO_VERSION. - Кэш под shared-хостинг reg.ru (без Redis/LiteSpeed): WP Super Cache на mod_rewrite; root-cause за nginx-прокси — детект HTTPS через
X-Forwarded-Proto; security-заголовки в.htaccess(mod_headers), т.к. WPSC отдаёт кэш мимо PHP. - Безопасные миграции: client→case через swap
post_type(слаги/мета 1:1) + структурный 301-хук вinc/rewrites.php(плагин Redirection не подхватывал первое regex-правило); удаления — через draft+rename (корзина на сервере отключена).
Результат
Подтверждённые эффекты (со ссылкой на источник):
- KPI ТЗ по весу/бандлам — PASS с запасом ≥2,3×: вес ≤526 КБ, JS ≤79 КБ, CSS ≤58 КБ gzip, CLS=0 при лимитах ТЗ 1,2 МБ / 300 / 200 КБ (источник:
docs/reports/phase8-tz-compliance.md, цит. вdocs/progress.md/docs/handoff.md). LCP лабораторно хорош, INP/CWV на проде — подтвердить после выката. - Весь контент front-страниц редактируется из админки — 9 лендингов + главная + auth/legal (58 layout-ов, 366 ассетов; источник:
docs/progress.md§8B-2). - Чистка/гигиена: плагины 41→14, mu-plugins 11→3, 2,23 ГБ бэкапов + 127 МБ GeoIP из вебрута, uploads 332→206 МБ, 457 WebP, кэш-хит TTFB 37→19 мс (источник:
docs/progress.mdФ2/6B/6C-D/6E). - QA против dist: 10 находок, критичных (P0) нет; фиксы задеплоены и верифицированы (источник:
docs/reports/phase7-qa-report.md). - Сдача: все 11 правок заказчика (7 кластеров) завершены и верифицированы; подготовлены руководство админа и отчёт (источник:
docs/handoff.md,docs/progress.md).
Не зафиксировано (уточнить): факт и дата прод-выката (на момент артефактов прод на Tilda, WP на staging за maintenance); бизнес-метрики (трафик/конверсии) после переезда.
Стек и обоснование
WordPress 7.0 + классическая PHP-тема (не FSE) — реюз рабочего бэкенда предыдущей команды и требование ЧПУ/шаблонов из ТЗ. SCF вместо nulled ACF Pro — снятие юридического/security-риска при API-совместимости (field groups в PHP переносятся без экспорта). Contact Form 7 (+ conditional-fields, honeypot, Flamingo, FluentSMTP) — формы строго как в dist. Yoast SEO — JSON-LD и мета-шаблоны. WP Super Cache (а не LiteSpeed из ТЗ) — на reg.ru нет LiteSpeed/Redis, обосновано как замена. Фронт-эталон: HTML/CSS/JS, vanilla app.js, Splide (карусели), GLightbox (лайтбокс), intl-tel-input (маска телефона, локально), self-hosted variable-шрифт Golos Text, WebP/AVIF через <picture>. Инструменты: WP-CLI, rsync-деплой, git (локально, без remote), Composer + phpcs/WPCS, @wordpress/scripts (eslint/stylelint), Playwright для визуального QA.
Роль ИИ в проекте
Проект — образцовый AI-augmented кейс, разработан в Claude Code (Opus 4.8, max effort). Конкретные артефакты:
- Doc-driven development:
CLAUDE.md(архитектура/правила), парные журналыdocs/progress.md+docs/handoff.md(хронология по фазам, решения, предостережения), система памяти проекта (MEMORY.md+ файлыcustomer-revisions-2026-06,server-ops-quirks,phase8e-progress,phase8d-perf,next-task-8b2). - Промпт-инжиниринг и мультиагентная оркестрация:
docs/prompts/phase8-deep-audit-and-plan.md— детальный промпт, запускающий 4–5 параллельных субагентов (Agent→Explore/general-purpose) по подсистемам (сервер/код/веб-ресёрч/Playwright) с централизованным синтезом; на инициализации — 8 параллельных аудиторов; для admin-guide — 3 параллельныхExplore-субагента. Жёсткие гард-рейлы в промпте: READ-ONLY на сервере, доказательность каждого утверждения, «не доверять старым аудитам слепо», запрет галлюцинаций про версии. - Методология superpowers:
brainstorming → writing-plans → executing— спеки и планы по кластерам вdocs/superpowers/specs/иdocs/superpowers/plans/(датированные файлы на каждый кластер), решения черезAskUserQuestion(D-A.D-J),TodoWrite/TaskCreate. - Цикл research→audit→implement: веб-ресёрч практик WP 7.0 с источниками и датами (
docs/reports/phase8-best-practices-2026.md) перед планированием. - Playwright MCP для визуального QA и пиксельной сверки темы с dist (129 логов прогонов в
.playwright-mcp/), автологин-скриншоты для руководства админа. - Безопасность процесса: авто-классификатор блокирует SSH/деплой-команды агента к тест-серверу — выкат запускает пользователь вручную (
!), агент делает сверку через curl/Playwright.
Инженерные вызовы
- Редактируемость «всего» без потери pixel-perfect — спроектирована библиотека из 58 переиспользуемых ACF Flexible Content layout-ов с вариантами hero/cta_form; ловушка:
instructionsACF выводятся сырым HTML — незакрытые теги-примеры ломали DOM редактора (решеноesc_html); top-level поля пер-страничных групп требуют префиксныхname/уникальных key (иначе репитеры не читались). - Окружение reg.ru как данность: нет Redis/LiteSpeed, Apache за nginx-прокси — кэш и security-заголовки пришлось решать через mod_rewrite/mod_headers и
X-Forwarded-Proto; статика отдаётся nginx-ом мимо.htaccess(заголовки на ассетах — тикет хостеру). - Yoast на staging:
WP_ENVIRONMENT_TYPE=stagingотключает canonical/indexables — потребовалась оговорка «на проде появится сам» + фильтр-гарантия/cases/. - Наследие предыдущей команды: обратный аудит дедупа экспертов (реальный контент был в «старых» записях, а не «новых»-заглушках); мёртвый плагин
smartway-tilda-fallbackс хардкод-путём прошлого автора; D1-миграция при отключённой корзине. - Регресс «пропала кнопка Обновить во всех Options» — ложно списан на роли 8E; реальная причина —
display:noneна колонке сабмита в admin-CSS (на SCF кнопка рендерится только в боковой колонке). Диагностика по view-source отделила клиентскую причину от серверной.
Услуги в проекте
- аудит
- доработка legacy
- миграция
- разработка
- деплой/DevOps
- SEO
- 152-ФЗ/ПДн (согласия)
- производительность/CWV
- контент-модель/редактируемость
- документация
- QA