How I Used Claude Code to Ship a Pixel-Matched WooCommerce Store With ERP Sync
A women's clothing brand in Russia needed an online store synced to their inventory system, built to 2026-9-13 18:28:6 Author: hackernoon.com(查看原文) 阅读量:19 收藏

A women's clothing brand in Russia needed an online store synced to their inventory system, built to match an existing React prototype pixel for pixel, on a budget that ruled out any of the usual enterprise platforms. I built it as a solo developer, on WordPress and WooCommerce, with Claude Code writing most of the code while I did the architecture, task design, and review. This is a piece about what that combination is actually good for, not the marketing version.

Skip the country-specific detail and the shape of the problem will look familiar to a lot of US freelancers and small agencies: a client with a real inventory system, a design that has to be reproduced exactly instead of approximated, and a budget that doesn't clear the bar for the platform everyone defaults to.

The default answer was too expensive, and it didn't fit the design

The client's inventory lives in 1C, the ERP and point-of-sale system that runs most Russian retail: a corporate accounting and inventory platform that only talks to the outside world through XML files. When a Russian merchant says "sync with 1C," the standard answer is: build on Bitrix, the dominant commercial CMS there, which ships a stock 1C exchange module and a large pool of integrators who already know it. Every market has its version of this default: the platform that ships a plugin for whatever the local business-software incumbent is, and that agencies reach for because that's what they already know how to staff and bill for.

For a one-location boutique, that default breaks on two fronts.

Cost. A Bitrix license, the annual renewal, and integrator fees add up to a budget close to what this entire open source build cost, end to end. Hard to justify for a single retail location.

Design. The client didn't want a theme with a catalog bolted onto it. They had a React prototype with a specific quiet-luxury look, a four-color palette, Lora and Raleway typography, zero border radius everywhere, and they wanted it reproduced exactly. Forcing that onto a stock theme takes longer than building one from scratch.

None of the actual requirements went away just because the budget was small. The store needed real-time stock from 1C (clothing means variable products, and every size-color combination carries its own count), card and instant-payment processing through a local processor, courier delivery integration, a cookie banner and consent checkboxes for Russia's data-privacy law, and ecommerce event tracking. Full functionality, minimal budget, a custom design, all at once.

The bet was on two things: a free WordPress and WooCommerce stack, and an AI coding agent standing in for a team.

The stack

  • CMS: WordPress with a fully block-based theme (FSE) built from scratch, no page builder plugins
  • E-commerce: WooCommerce and WooCommerce Blocks, mini cart through the Store API
  • Backend: PHP 8, a modular `inc/` structure, custom fields registered in code instead of through an admin UI
  • Frontend: plain ES modules, no jQuery, `IntersectionObserver` for scroll animations, `history.pushState` for filter state, icons as an inline SVG sprite
  • Design tokens: `theme.json` as the single source of truth, with CSS variables generated from it
  • ERP sync: 1C over the CommerceML protocol, real time
  • Payments and logistics: local card and instant-payment processing, courier delivery, email, analytics
  • Hosting: a Russian hosting provider, deployed over SSH
  • AI tooling: Claude Code, plus MCP servers for Playwright browser checks and SSH deploys

A block theme as the design system, not a page builder

WordPress with a fully block-based theme, no Elementor, no page builder plugin of any kind. On a budget project that's not a style preference, it's arithmetic: every builder plugin costs you performance, chains you to someone else's update schedule, and adds a layer of abstraction between the design and the actual code.

The design system from the React prototype moved into `theme.json`, WordPress's native token file. Four colors, an 8px spacing scale, two typefaces. WordPress generates CSS variables from that file automatically, and every stylesheet in the theme references only those variables:

:root {
  --color-bone: /* background, roughly 70% of the canvas */;
  --color-ink: /* text and UI */;
  --color-bordeaux: /* sale badges and accents */;
  --color-pine: /* dark navigation */;
}

Text hierarchy comes from transparent variants of the ink color rather than a stack of grays. Border radius is zero everywhere except pill-shaped tags. That rigid rule set turned out to matter more once the AI agent entered the picture, which I'll get to.

The PHP layer stays boring on purpose. `functions.php` does nothing but wire up modules:

// functions.php: wiring only, no logic
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' );

One file, one responsibility. Repeating sections became block patterns. Header and footer became template parts. WooCommerce's default templates got overridden only where the stock markup actually conflicted with the design, not wholesale.

What vibe coding looks like on a real project, not a demo

The agent didn't build the store on its own. It wrote most of the code while I handled architecture, task decomposition, and review. That's not less work than building it by hand. It's the same amount of decision-making at a different throughput.

Claude Code reads a project instructions file, `CLAUDE.md`, at the start of every session, and that turned out to be the load-bearing piece. I put the entire design system in there as a list of prohibitions: exactly four colors, no raw hex values anywhere in the codebase, radius is zero, headings are uppercase with letter spacing, spacing only comes from the 8px scale. Left alone, an LLM improvises constantly, and the improvisation is exactly what breaks a tight design system. With the hard rule in place, when the agent needs a new shade it doesn't paste a hex code, it derives one with `oklch()` from an existing token, because the file tells it that's the only allowed move.

The other thing that mattered was memory between sessions, because the agent's context window is finite and the project ran for months. Every real lesson learned along the way, "WooCommerce Blocks doesn't load jQuery," "1C's delta exports silently wipe product variations," got written to a markdown file the agent reads on the next session. A new session doesn't start from zero. It starts from a digest of every trap already stepped in once, which is basically an engineer's external long-term memory, except the one reading it is an agent instead of a person picking a project back up after a week off.

And then there's verification, which is the part I'd push back on hardest if someone tried to skip it. The agent has Playwright access through MCP, so it can open the live page, click through a flow, take a screenshot, and diff it against the prototype itself, instead of me eyeballing a screenshot and taking its word for it. The rule is simple: no "fixed" claim without a real check to back it up. That rule earned its keep on a bug where product card links stopped working, but only on desktop, and only in production. The agent reproduced it with an actual Playwright click and traced the cause to `setPointerCapture` inside the image carousel: it was intercepting pointer events and retargeting the click from the product link to the carousel track underneath it. Nobody was going to spot that by reading the carousel code, which looked completely fine on its own.

Where the agent falls short, honestly: it will confidently fix the wrong root cause if you don't force a reproduction first. It'll quietly drift outside the design system the moment a rule is ambiguous instead of explicit. And it loses the thread on long tasks without something external to remind it what already happened. All three are process problems, not model problems, which is why this piece spends more time on process than on prompts.

The ERP integration: the part nobody warns you about

This ate more hours than anything else in the project, and it's the part most relevant if you're wiring any ERP or POS system into an ecommerce platform over an XML feed, not just this specific stack.

The sync runs on CommerceML, an XML-based exchange protocol: the ERP exports packets on a schedule and on events, real-time mode was on for this project, and a plugin on the WordPress side parses them and updates the catalog. Simple in outline. The traps live in the details, and CommerceML being a Russian national standard means the XML element names below are genuinely Russian words, not obfuscation.

The first one: stock counts that weren't real. The storefront showed the wrong stock even though the sync ran clean, no errors, no warnings. The cause only surfaced after diffing the raw XML against what actually landed in the database. In the version of the protocol we were on, stock arrives in separate files with a nested structure, broken out per warehouse:

<Предложение>
  <Ид>product-guid#variation-guid</Ид>
  <Остатки>
    <Остаток>
      <Склад>
        <Ид>warehouse-guid</Ид>
        <Количество>3</Количество>
      </Склад>
    </Остаток>
  </Остатки>
</Предложение>

The plugin's parser expected a flat quantity field one level up and silently skipped the nested version. No error anywhere in the pipeline, the sync reports success, and the data is just wrong. Fixed with a parser patch, and since then I diff the plugin's code before every update, because the next release could quietly bring the old bug back.

There's a second one that took longer to untangle: product properties and variation characteristics are handled as two unrelated mechanisms in this protocol, with separate code paths. A color set up as a property and a size set up as a characteristic land in WooCommerce through completely different logic, and until you trace both paths independently, the result is unpredictable.

Third, the fast sync sends delta chunks instead of the full catalog on every run, and the plugin was rebuilding each product's entire variation set from every chunk it received. Any variation absent from that particular chunk just vanished, so the size range was slowly draining out from under us without anyone noticing at first. I ended up writing a mode that preserves variations across partial exports, plus a cleanup pass, since roughly a thousand orphaned variations had piled up in the database by the time we caught it.

Last, attribute terms were getting created with GUID-based slugs instead of readable ones, which broke filter URLs and made the admin panel unreadable. A mapping table plus a repair script that runs after every sync took care of that one.

The honest takeaway: an ERP-to-WordPress sync can run reliably in production, ours does, in real time. But "install the plugin and walk away" is not a real option. Budget time to read the plugin's source, patch its parser, and write your own verification scripts.

The layer nobody puts in the estimate

Payments, shipping, and email were the boring, standard part: local card and instant-payment processing, courier integration, transactional email, ecommerce analytics events. Swap in a different payment processor, a different carrier API, a different analytics platform, and the shape of this work barely changes anywhere in the world.

What does get skipped in estimates is compliance. Russia has its own data-privacy law; most other markets have their own version of the same thing, whether that's a national statute or a state-level one. A cookie banner, consent checkboxes on every form, terms accepted at checkout. None of it is technically hard. All of it tends to surface in the final week of a project and push the deadline if nobody planned for it up front.

WooCommerce Blocks quietly dropped jQuery, and a lot of tutorials don't know it yet

Modern WooCommerce with block-based templates does not load jQuery on the storefront. At all. Every classic tutorial snippet built on `$('.variations_form').on('found_variation', …)` has nothing left to attach to. For a block theme, I had to write a native variation resolver from scratch: collect the selected attributes, match them against the variation data, update price, photo, and availability.

// No jQuery here: WooCommerce Blocks doesn't load it.
const match = variations.find((v) =>
  Object.entries(selected).every(
    ([attr, value]) => !v.attributes[attr] || v.attributes[attr] === value
  )
);

Same story elsewhere in the frontend: AJAX catalog filters render inside the block product template, filter state lives in the URL through `history.pushState` so a filtered link survives being forwarded to someone else, the mini cart runs on the Store API, scroll animations use `IntersectionObserver` and respect `prefers-reduced-motion`. None of it is exotic. It's just modern frontend work that the WordPress ecosystem still expects you to hand-assemble.

What shipped

A working store on a custom block theme that matches the prototype exactly. A catalog with AJAX filtering, variable product cards with size and color options, a wishlist, a product page with a swipe gallery on mobile.

Real-time sync with the ERP: prices, stock, and variations arrive without anyone touching a spreadsheet. After the stock parser fix, the storefront numbers match the warehouse.

The regional layer: card and instant payments live, courier delivery live, privacy compliance closed out.

Iteration speed held up under real client feedback too. Two full rounds of revisions, about thirty items ranging from typography tweaks to restructuring entire blocks, each round cleared in a few days. Total development time was measured in weeks.

And the budget point holds: zero dollars in platform licenses. WordPress, WooCommerce, and the rest of the stack are open source. The client's money went to actual work and hosting, not to a renewal invoice for a boxed platform.

When this approach fits, and when it doesn't

It fits a small or mid-size store with a custom design, an ERP that isn't a deep enterprise system, a budget that genuinely constrains the platform choice, and a developer willing to read exchange XML instead of just clicking through a plugin's settings page.

It doesn't fit a high-volume marketplace processing thousands of orders a day, real-time multi-warehouse reservation logic, or a client whose procurement process requires vendor support contracts. In those cases, a boxed platform, or a custom build on a heavier stack, earns its cost.

On the AI part specifically: Claude Code didn't replace a developer on this project. It replaced part of a team. I wouldn't have shipped something this size, alone, on this timeline, without it, or I'd have shipped it on a very different budget. But hand the agent a project with no rules file, no memory between sessions, and no requirement to verify its own claims, and it produces code that's confident and wrong in roughly equal measure. Building that process mattered more than any prompt I wrote.


文章来源: https://hackernoon.com/how-i-used-claude-code-to-ship-a-pixel-matched-woocommerce-store-with-erp-sync?source=rss
如有侵权请联系:admin#unsafe.sh