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

Smartway — переезд корпоративного сайта с Tilda на WordPress

B2B-сервис управления командировками (travel-tech SaaS) · Travel-tech / корпоративные командировки (business travel management, B2B SaaS)

Ведущий fullstack-разработчик WordPress (backend-фокус): аудит, адаптация темы, бэкенд, SEO, DevOps

  • 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
активных плагинов после чистки (Фаза 2)
11 → 3
mu-plugins (удалён agent-bridge → закрыта дыра REST sw-agent/v1)
22
страницы статичной вёрстки dist перенесены в тему
58
ACF Flexible Content layout-ов в библиотеке (9 лендингов + главная + auth/legal, весь контент в админку)
366
ассетов фронта импортировано в медиатеку (SVG через safe-svg)
457
изображений сконвертировано в WebP (cwebp -q80, used-only)
19
записей client → case мигрировано + 301-редиректы /clients/* → /cases/* (D1)
10 → 6
дедупликация экспертов (CNT-03) с сохранением реального контента + 301 surname → full-name
≥2,3×
запас по KPI ТЗ: вес ≤526 КБ, JS ≤79 КБ, CSS ≤58 КБ gzip, CLS=0 (лимиты ТЗ: 1,2 МБ / 300 / 200 КБ)
37 → 19 мс
серверный TTFB кэш-хита после WPSC mod_rewrite + preload (6E)
2,23 ГБ + 127 МБ
ai1wm-бэкапы и осиротевший GeoIP вынесены из вебрута; uploads 332 → 206 МБ; −260 ревизий (6B)
10 находок (0×P0, 1×P1, 3×P2, 4×P3, 2×info)
QA-аудит Фазы 7 против dist (43 скриншота)
31 раздел / 40 скриншотов
HTML-руководство администратора (самодостаточное, офлайн)
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→шаблоны), общий shell header-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 — через фильтры Yoast wpseo_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 параллельных субагентов (AgentExplore/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; ловушка: instructions ACF выводятся сырым 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