Интернет-магазин с реал-тайм синхронизацией с 1С - то, что агентства обычно продают как отдельный дорогой проект с обязательным Битриксом в комплекте, - обошёлся клиенту в ноль рублей на лицензии. Собран на WordPress и WooCommerce, а большую часть кода написал не я, а Claude Code. Если вы считаете, что учёт в 1С автоматически означает Битрикс и студийный бюджет, этот кейс - повод пересмотреть исходные данные.
Коротко о проекте, если вам нужна выжимка, а не история целиком: интернет-магазин дизайнерской одежды на WordPress + WooCommerce с реал-тайм синхронизацией остатков и цен с 1С:Розница по протоколу CommerceML 3.1. Дизайн - точная копия готового React-прототипа, кастомная блочная тема (FSE) без единого page-builder-плагина. Бэкенд на PHP 8, вариативные товары с размерами и цветами, приём платежей через ЮKassa и СБП, доставка СДЭК, соответствие 152-ФЗ. Большую часть кода написал AI-агент Claude Code - человек проектировал архитектуру, ставил задачи и проверял результат через живые браузерные тесты на Playwright. Бюджет: 0 ₽ на лицензии за счёт open-source стека вместо коробочного решения.
Заказчик - бренд женской одежды из Екатеринбурга - пришёл с вводными, на первый взгляд простыми. Товар ведут в 1С:Розница. Дизайн уже готов, и воспроизвести его нужно один в один, а не «в целом похоже». А вот бюджет задавал жёсткие рамки сразу: ни лицензии за сто тысяч в год, ни команда из шести человек в смету не входили. Один разработчик, open-source стек, и сроки, которые заказчик из вежливости назвал сжатыми, а по факту это было просто мало времени.
Дальше в статье - версии компонентов и границы интеграции для тех, кто хочет повторить у себя, разбор четырёх реальных граблей на 1С, честный список того, что AI-агент делает хорошо и что плохо, и отдельный блок troubleshooting с симптомами, причинами и шагами репро. Если вы здесь за конкретикой, а не за вдохновляющей историей, таблица ближе к концу статьи, скорее всего, самая полезная часть.
Проблема: бутик-магазин без бутик-бюджета
В России, если магазину нужен учёт в 1С, разработчики почти хором дают один совет: бери Битрикс. Загляните в поисковую выдачу по запросу про интеграцию 1С с сайтом - там сплошной Битрикс, и это не случайность. Логику я понимаю: штатный модуль обмена, коробочные тарифы, армия интеграторов, которые это уже сто раз делали. Вопрос в другом: подходит ли эта логика бутику дизайнерской одежды с одной точкой продаж?
Не подходит - и ломается ровно в двух местах: деньги и дизайн.
С деньгами всё прямолинейно. Лицензия «1С-Битрикс: Малый бизнес» плюс ежегодные продления плюс работа интегратора - и в сумме набегает бюджет размером со всю разработку на open source. Для одной розничной точки это уже не расход, а перерасход, который сложно оправдать чем-то, кроме привычки.
С дизайном сложнее. Заказчику не нужен «ещё один шаблон с каталогом» - нужна точная копия готового прототипа: четыре цвета, шрифты Lora и Raleway, нулевые радиусы, воздух в сетке. Натянуть такой дизайн на чужую тему можно. Вопрос - какой ценой: выйдет дольше, чем написать свою тему с нуля, а результат всё равно останется «примерно похоже».
И при всём этом список требований не сокращается ни на пункт: реал-тайм остатки из 1С:Розница (одежда - товар вариативный, у каждого размера и цвета свой сток), ЮKassa со СБП, доставка СДЭК, cookie-баннер с согласиями по 152-ФЗ, ecommerce-события в Яндекс.Метрике.
Получается набор условий, который на бумаге выглядит взаимоисключающим: функциональность взрослого магазина, минимальный бюджет, дизайн под копирку - и всё одновременно, без права выбрать два из трёх. Ставка была на связку из двух вещей: бесплатный WordPress с WooCommerce и AI-агент вместо команды разработчиков.
Решение
Вот весь стек проекта целиком, а дальше разберу каждый пункт по отдельности:
- CMS: WordPress, полностью блочная тема (FSE) с нуля, без page-builder-плагинов
- E-commerce: WooCommerce + WooCommerce Blocks, мини-корзина через Store API
- Бэкенд: PHP 8, модульная структура
inc/, ACF (поля регистрируются кодом, не через UI) - Фронтенд: ES-модули без jQuery,
IntersectionObserverдля анимаций,history.pushStateдля состояния фильтров, иконки Lucide инлайн SVG-спрайтом - Дизайн-токены:
theme.jsonкак единый источник, CSS-переменные генерируются из него - Обмен с 1С: 1С:Розница, протокол CommerceML 3.1, реал-тайм
- Платежи и сервисы: ЮKassa (карты, СБП), СДЭК, Unisender, Яндекс.Метрика с ecommerce-событиями
- Хостинг и деплой: NetAngels, деплой по SSH
- AI-инструменты: Claude Code + MCP-серверы (Playwright для проверки в браузере, SSH для деплоя)
Версии и границы интеграции
Для тех, кто хочет не просто прочитать, а повторить у себя - версии на момент публикации:
- WordPress 7.0.2, тема требует минимум 6.6
- WooCommerce 10.7.0
- PHP 8.2 - тема явно требует эту версию, ниже она не соберётся
- ACF (Advanced Custom Fields) 6.8.3, поля регистрируются кодом, а не через UI
- Обмен с 1С: открытый плагин «Data Exchange for WooCommerce and 1C:Enterprise» (автор Danil Semelenov), версия 0.9.20, поверх протокола CommerceML 3.1
- 1С:Розница - релиз со стороны клиента, версию платформы здесь не фиксирую: это не то, что контролирует разработчик сайта
Стоит сразу сказать, что плагин обмена решает сам, а что нет, чтобы не переоценить готовую коробку. Он парсит XML-пакеты и обновляет каталог, остатки и цены. Он не решает: не пересчитывает автоматически счётчики товаров у терминов атрибутов после импорта (это ниже, в troubleshooting), не разруливает конфликт, если один товар редактируют одновременно на сайте и в 1С, и не валидирует данные на стороне 1С - мусор на входе остаётся мусором на выходе, если не поставить свой слой проверок.
Стек и архитектура: блочная тема как дизайн-система
В основе - WordPress с полностью блочной темой, FSE, без единого page-builder-плагина. Для проекта с таким бюджетом это не вопрос вкуса, а необходимость: любой конструктор вроде Elementor - это просадка производительности, зависимость от чужих релизов и лишняя прослойка между дизайном и кодом. Экономить на этом было попросту нельзя.
Дизайн-систему из React-прототипа я перенёс в theme.json целиком, и она стала единственным источником правды для токенов: четыре цвета в палитре, шкала отступов на базе 8px, два шрифта. WordPress сам генерирует из этого CSS-переменные, а весь остальной CSS дальше ссылается только на них:
:root {
--color-bone: /* фон, ~70% площади */;
--color-ink: /* текст и UI */;
--color-bordeaux: /* sale и акценты */;
--color-pine: /* тёмная навигация */;
}Иерархия текста держится на прозрачности основного цвета, а не на палитре из десяти оттенков серого. Радиусы везде нулевые, кроме капсульных тегов. Забегая вперёд: этот жёсткий свод правил ещё не раз сыграет на руку именно в AI-разработке, и вот почему.
Правда, даже жёсткие правила не защищают от всего. В какой-то момент фоновый токен поменяли по решению заказчика - с тёплого на нейтральный. Правило «никаких сырых hex» отлично соблюдалось для всех новых значений. Но не для фолбэков. В нескольких местах PHP-кода, где рендерятся свотчи товаров, лежал захардкоженный запасной цвет на случай, если у товара нет значения из 1С - и его никто не тронул, потому что формально это не «новое решение», а старое значение по умолчанию. Заметили не сразу: свотчи у товаров без цвета из 1С продолжали рисоваться старым оттенком поверх уже нового фона. Вывод простой и не особо приятный: правило про сырые значения нужно распространять и на дефолты, а не только на видимые новые решения, иначе дыра остаётся ровно там, где её никто не ищет.
PHP-слой я организовал без затей. functions.php сам не делает ничего, только подключает модули из inc/, у каждого файла ровно одна зона ответственности:
// functions.php: только подключение, никакой логики
require_once get_theme_file_path( 'inc/setup.php' );
require_once get_theme_file_path( 'inc/assets.php' );
require_once get_theme_file_path( 'inc/woocommerce.php' );
require_once get_theme_file_path( 'inc/ajax-handlers.php' );Повторяющиеся секции ушли в block patterns, шапка с футером - в template parts. WooCommerce-шаблоны я переопределял точечно, только там, где стандартная разметка спорила с дизайном.
AI-workflow: как выглядит вайб-кодинг на реальном проекте
Магазин агент не написал сам - так это не работает. Он написал большую часть кода, я спроектировал архитектуру, ставил задачи и принимал результат. Работы от этого меньше не стало. Изменилась пропускная способность.
Держится это на трёх вещах, и вот на каких.
Первая - контракт в CLAUDE.md, файле инструкций, который Claude Code перечитывает заново каждую сессию. Я вынес туда всю дизайн-систему в виде прямых запретов: палитра строго из четырёх цветов, сырые hex-коды под запретом, радиус ноль, заголовки uppercase с трекингом, отступы только по 8px-шкале. Дайте LLM волю - и она с удовольствием начнёт импровизировать. Жёсткие формулировки эту вольность убирают напрочь: когда агенту нужен новый оттенок, он не пишет hex-код, а выводит его через oklch() от существующего токена.
Вторая - файловая память между сессиями. Контекст у агента конечный, а проект растянулся на месяцы. Возникает очевидный вопрос: как не наступать на одни и те же грабли по кругу? Ответ прозаичный - каждый урок, который стоил времени («в WooCommerce Blocks нет jQuery», «дельта-выгрузки 1С стирают вариации»), уходил в markdown-файлы памяти. Новая сессия открывается не с чистого листа, а с конспекта всех прошлых ошибок. По сути, это внешняя долговременная память инженера - просто читает её не человек.
Третья - проверка в браузере вместо проверки на глаз. У агента есть Playwright через MCP: он открывает страницу сам, кликает, снимает скриншот, сравнивает с прототипом. Правило жёсткое: фраза «баг починен» без живого прогона не принимается. Один раз это правило спасло напрямую. Клики по карточкам товаров не работали, причём только на десктопе и только на проде - казалось бы, откуда там вообще взяться разнице? Агент воспроизвёл баг реальным кликом в Playwright и докопался до причины: setPointerCapture в карусели перехватывал pointer-события и подменял цель клика, вместо ссылки срабатывал трек карусели. На глаз такое не найти - код карусели выглядел абсолютно рабочим.
А вот что агент делает плохо, и об этом стоит сказать честно, а не только хвалить. Он уверенно чинит не ту причину, если не заставить его сначала воспроизвести баг руками. Тащит в вёрстку решения в обход дизайн-системы, стоит правилам чуть размыться. Теряет нить на длинных задачах без внешней памяти.
Один конкретный пример последнего: агент как-то привязал логику меню к числовому ID конкретной записи меню в WordPress вместо резолва по зарегистрированной theme location. Работало ровно до тех пор, пока контент не переэкспортировали и ID не разъехались - тогда меню тихо перестало подсвечивать нужный пункт, без единой строчки в логах. Тот же класс проблемы, что и с фолбэк-цветом из прошлого раздела: код формально рабочий, но хрупкий, и общее правило «не хардкодь» само по себе не спасает, если не проговорить его для каждого конкретного места - ID записей точно так же, как цвета и отступы.
Все эти проблемы лечатся процессом, не промптом - отсюда и такой перекос статьи в сторону процесса, а не только кода.
Интеграция с 1С: CommerceML и грабли, о которых молчат мануалы
Это самая дорогая по времени часть всего проекта. И, подозреваю, самый полезный раздел для тех, кто гуглит интеграцию 1С с сайтом не на Битриксе - предупреждаю сразу, дальше будет сухо и по делу.
Схема на бумаге простая: 1С:Розница по расписанию и по событию (реал-тайм обмен включён) выгружает XML-пакеты, плагин на стороне WordPress их разбирает и обновляет каталог. Грабли, как обычно, живут не в схеме, а в деталях.
Грабля первая: остатки, которых на самом деле не было. На витрине висели неверные цифры, хотя обмен формально отрабатывал без единой ошибки - как так, если ошибок нет вообще? Причину я нашёл только диффом сырого XML против того, что реально доехало до базы. В CommerceML 3.1 остатки приходят отдельными файлами rests_*.xml, и структура там вложенная: остаток разбит по складам внутри <Остатки><Остаток><Склад>:
<Предложение>
<Ид>guid-товара#guid-характеристики</Ид>
<Остатки>
<Остаток>
<Склад>
<Ид>guid-склада</Ид>
<Количество>3</Количество>
</Склад>
</Остаток>
</Остатки>
</Предложение>Парсер плагина ждал плоский <Количество> уровнем выше и молча игнорировал вложенный вариант. Никаких ошибок, никаких предупреждений - обмен выглядит рабочим, а данные попросту врут. Вылечилось патчем парсера. С тех пор я перед каждым обновлением 1С-плагина смотрю дифф его кода: следующий апдейт вполне может тихо вернуть старое поведение, и никто об этом не предупредит.
Грабля вторая: атрибуты живут в двух не связанных друг с другом пайплайнах. Свойства номенклатуры («ЗначенияСвойств») и характеристики вариаций («ХарактеристикиТовара») в CommerceML - разные механизмы, и плагин ведёт их разными путями. Цвет, заведённый как свойство, доедет до WooCommerce иначе, чем размер, заведённый как характеристика. Пока оба пайплайна не разложишь по шагам вручную, результат остаётся непредсказуемым.
Грабля третья: дельта-выгрузки воюют с вариациями. Быстрый обмен шлёт не весь каталог, а чанки-дельты. Плагин на каждый такой чанк пересоздавал набор вариаций товара - и всё, что не попало именно в этот чанк, тихо исчезало. Размерная сетка редела сама по себе, без видимой причины, что поначалу изрядно сбивало с толку. Спасло включение режима сохранения вариаций при частичных выгрузках плюс разовая чистка базы: за время отладки набежала почти тысяча вариаций-сирот.
Грабля четвёртая: GUID вместо человеческих слагов. Термины атрибутов создавались со слагами-GUID, а это убивало и URL фильтров, и читаемость админки. Решил константами соответствия плюс repair-скриптом, который гоняю после каждого обмена.
Отдельно стоит рассказать про случай, который граблей вообще не был - это было решение, а не баг. У части товаров 1С отдаёт цвет одной строкой сразу на два цвета, вроде «белый / зелёный», просто потому что так заведена характеристика на стороне товароучётки. Разбить такую строку на два отдельных атрибута технически можно. Но это решение про данные, не про парсинг, и его нельзя тихо принять в коде - я вынес вопрос заказчику. Ответ оказался неожиданным: не делить на два термина, а рисовать один свотч, разбитый по диагонали на оба цвета. Не самое очевидное решение технически, зато точное и от человека, который реально понимает мерч. Мораль простая: не каждая странность в данных 1С - баг, который нужно тихо пофиксить. Иногда это вопрос, который нужно задать, а не решить за заказчика.
Если резюмировать раздел коротко: интеграция 1С с WordPress в итоге работает стабильно, в проде живёт реал-тайм обмен. Но забудьте про сценарий «поставил плагин и ушёл пить кофе» - придётся читать код плагина, чинить парсер и писать свои проверочные скрипты. Закладывайте это время в оценку сразу, а не когда оно всплывёт само.
Платежи, доставка и 152-ФЗ
Российский контур собран из стандартных кубиков: ЮKassa с картами и СБП на приёме платежей, СДЭК и Почта России на доставке, Unisender на рассылках, ecommerce-события Яндекс.Метрики на аналитике. А вот про что регулярно забывают в оценке бюджетных проектов - это 152-ФЗ: cookie-баннер, чекбоксы согласия на обработку персональных данных в формах, оферта в чекауте. Технически там нет ничего сложного. Но именно такие задачи всплывают на последней неделе и двигают срок, если не заложить их с самого начала.
Фронтенд без jQuery: сюрприз от WooCommerce Blocks
Современный WooCommerce с блочными шаблонами не тянет jQuery на витрину. Совсем. Классический сниппет из любого туториала вида $('.variations_form').on('found_variation', …) просто некому исполнять - и это открытие стало небольшим сюрпризом уже по ходу разработки. Для блочной темы я написал свой резолвер вариаций на чистом JS: собираем выбранные атрибуты, ищем совпадение в данных вариаций, обновляем цену, фото и доступность:
// jQuery отсутствует: WooCommerce Blocks его не подключает.
const match = variations.find((v) =>
Object.entries(selected).every(
([attr, value]) => !v.attributes[attr] || v.attributes[attr] === value
)
);Из той же оперы: AJAX-фильтры каталога рендерятся прямо внутрь блочного шаблона товаров, состояние фильтров живёт в URL через history.pushState (можно переслать ссылку с уже выбранными фильтрами), мини-корзина крутится на Store API. Скролл-анимации сидят на IntersectionObserver и уважают prefers-reduced-motion. Ничего революционного здесь нет - просто обычный современный фронтенд, который в WordPress почему-то до сих пор надо собирать руками.
Отдельная ловушка блочных тем, о которую я споткнулся уже на странице товара: прототип требовал sticky-колонку с инфой товара справа, пока левая колонка с фото скроллится. position: sticky в CSS был на месте, а работать отказывался. Причина оказалась в самом FSE: WordPress автоматически добавляет обёртки с классом is-layout-constrained и своими стилями вроде margin: auto вокруг блочного контента, и эти стили тихо ломают контекст, в котором sticky вообще может сработать. В devtools всё выглядело нормально: объявление есть, специфичность в порядке, а элемент всё равно едет со страницей вместо того, чтобы прилипнуть. Разбирался через ту же браузерную проверку из workflow - смотрел вычисленные стили не своего блока, а его родительских обёрток, и там нашёлся лишний layout-контейнер от самой FSE. Урок узкий, но конкретный: в блочных темах WordPress проблема со sticky или absolute часто не в вашем CSS, а в невидимой обёртке, которую сам WordPress вставил вокруг блока.
Типичные сбои: симптом, причина, чем чинили
Свод самых частых проблем проекта в одном месте - для тех, кто хочет быстро свериться, а не читать историю целиком.
Остатки не совпадают с витриной, хотя обмен прошёл без ошибок.
Причина: остатки в CommerceML 3.1 приходят вложенной структурой (<Остатки><Остаток><Склад>), а не плоским полем, плагин ждал старый плоский формат.
Чинили: патч парсера под вложенную структуру.
Проверка у себя: раскройте один rests_*.xml из выгрузки и сверьте, лежит ли <Количество> внутри <Склад> или уровнем выше - если внутри, у вас та же проблема.
Размерная сетка товара пустеет сама по себе без видимой причины. Причина: быстрый обмен шлёт дельта-чанки, плагин на каждый чанк пересоздавал весь набор вариаций, и то, что не попало в текущий чанк, удалялось. Чинили: режим сохранения вариаций на частичных выгрузках плюс разовая чистка базы от вариаций-сирот. Проверка у себя: сравните число вариаций товара до и после одной дельта-выгрузки - если после обмена их стало меньше без ручных изменений, симптом совпадает.
Фильтр по размеру показывает размеры, которых ни у одного товара нет в наличии.
Причина: WooCommerce не пересчитывает счётчик товаров у терминов атрибутов автоматически после импорта через 1С-плагин.
Чинили: принудительный пересчёт счётчиков термов после каждого обмена.
Проверка у себя: после обмена сравните count термина в базе с реальным числом товаров в наличии - если счётчик выше, это оно.
Свотч цвета у части товаров остаётся старого оттенка на новом фоне сайта. Причина: смена дизайн-токена не долетела до захардкоженного fallback-значения в PHP, которое подставляется, когда у товара нет цвета из 1С. Чинили: вынесли fallback в тот же токен, что и остальная палитра, вместо отдельного значения. Проверка у себя: найдите в коде дефолтные значения цветов отдельно от основной дизайн-системы - именно они отстают первыми при смене токенов.
Меню тихо перестаёт подсвечивать нужный пункт после переноса контента.
Причина: логика привязана к числовому ID конкретной записи меню, а не к зарегистрированной theme location, и ID изменился при экспорте-импорте.
Чинили: резолв через get_nav_menu_locations() вместо сравнения с литералом.
Проверка у себя: поищите в коде сравнения вида «равно конкретному числу» рядом с логикой меню или блоков - это кандидат.
Sticky-колонка на странице товара не работает, хотя CSS выглядит правильным.
Причина: автоматическая обёртка блочной темы FSE (is-layout-constrained) со своими layout-стилями ломает контекст, нужный для position: sticky.
Чинили: убрал лишний уровень вложенности layout вокруг sticky-блока.
Проверка у себя: в devtools смотрите computed-стили не своего блока, а его родительских обёрток - ищите чужой margin или display, который вы не писали.
Результат
Вот что уже стоит в проде на момент публикации этого текста.
Рабочий магазин на кастомной блочной теме, один в один повторяющей дизайн-прототип. Каталог с AJAX-фильтрами, вариативные карточки с размерами и цветами, избранное, страница товара со свайп-галереей на мобильных.
Реал-тайм обмен с 1С:Розница: цены, остатки и вариации едут из товароучётки без единого ручного дублирования. После фикса парсера остатков витрина наконец совпадает со складом.
Российский контур закрыт целиком: приём платежей через ЮKassa и СБП, доставка СДЭК и Почтой России, требования 152-ФЗ выполнены.
Показательна и скорость итераций: два полных пакета правок заказчика, тридцать пунктов (от типографики до перестройки блоков) разобраны за несколько дней каждый. Время разработки в итоге считали неделями, а не месяцами.
И бюджет: ноль рублей на лицензии. WordPress, WooCommerce и весь стек целиком - open source. Деньги заказчика ушли на работу и хостинг, а не на ежегодные продления коробочного решения.
Когда WordPress + AI подходит, а когда нет
Такой подход годится, если у вас:
- малый или средний магазин с кастомным дизайном;
- учёт в 1С без глубокого ERP-контура;
- бюджет, который решает многое;
- разработчик, готовый разбирать XML обмена руками, а не только жать «установить плагин».
И не годится - тут важно быть честным - если у вас:
- высоконагруженный маркетплейс с тысячами заказов в день;
- сложная логистика с резервированием по складам в реальном времени;
- корпоративное требование вендорской поддержки.
В этих случаях коробочное решение или кастом на другом стеке окупит себя быстрее.
Про AI-часть вывод у меня простой, хоть и не такой громкий, как могло бы показаться из заголовка. Claude Code не заменяет разработчика - он заменяет часть команды. Проект такого объёма в одиночку и в такие сроки без агента я бы не потянул, или потянул бы с совсем другим бюджетом. Но без выстроенного процесса (правил в CLAUDE.md, внешней памяти, обязательной проверки браузером) агент с уверенным видом выдаёт неверный код. И это, пожалуй, главный вывод всего проекта: настроить процесс важнее, чем научиться писать красивые промпты.
FAQ
Сколько стоит разработка интернет-магазина на WordPress? Порядок цифр в разы ниже, чем на коробочных платформах: нет платы за лицензии, меньше ручного труда благодаря AI-разработке. Точная стоимость зависит от дизайна, интеграций и размера каталога и считается по техническому заданию.
Можно ли интегрировать 1С с WooCommerce? Да, через протокол CommerceML - с реал-тайм обменом остатками и поддержкой вариативных товаров. Нюанс в том, что штатные плагины почти всегда требуют доработки напильником, подробности выше в разделе про 1С.
Что такое вайб-кодинг простыми словами? Это разработка, где рутинный код пишет AI-агент, а человек ставит задачи, проектирует архитектуру и принимает результат. Скорость растёт в разы, а качество держится исключительно на дисциплине проверок.
Заменяет ли Claude Code разработчика? Нет. Он закрывает часть команды: джуна-верстальщика, тестировщика на рутинных проверках, техписателя. Архитектура, декомпозиция задач и финальная приёмка так и остаются за человеком.
Работает ли WooCommerce с ЮKassa и СБП? Да. У ЮKassa есть официальный модуль для WooCommerce с оплатой картами и через СБП.