Developers
Developers
The two codebases behind the storefront, how the monorepo is laid out, which way dependencies point, and where to start reading.
Two codebases make up the product: the storefront, a Next.js 16 app in a pnpm monorepo, and the Companion plugin (Retail Store Companion), a WordPress plugin that adds what WooCommerce does not provide on its own. This section is for engineers extending either one. It covers the architecture, the rules the code enforces, and the reasons behind them. Those reasons are recorded as decision records in the storefront repository.
The two codebases
Section titled “The two codebases”| The storefront | The Companion plugin | |
|---|---|---|
| Repository | retail-store-frontend |
retail-store-companion |
| Runtime | Next.js 16 (App Router), React 19, Node 22 or newer | WordPress with WooCommerce (required), PHP 8.0 or newer |
| Language | TypeScript, fully strict | PHP (PSR-4 namespace WeLabs\RetailStoreCompaion\), plus React admin apps |
| Package manager | pnpm (pinned, workspaces) | Composer, plus npm for the admin apps |
| Talks to | WooCommerce Store API, WC REST v3, WP REST, the Companion’s REST namespace | Nothing upstream: it serves REST and extends WooCommerce’s responses |
| Tests | Playwright smoke suite (Demo Mode) and the Port contract suite (Vitest) | PHPUnit (main and integration suites), PHPCS |
| Read first | CLAUDE.md, then CONTEXT.md (the glossary), then docs/adr/ |
CLAUDE.md, then Architectur-docs/ |
The Companion’s PHP namespace, text domain, options and constants are spelled compaion (one n short). Its REST namespace is
spelled retail-store-companion. Match the surrounding code; don’t “fix” either spelling.
The storefront monorepo
Section titled “The storefront monorepo”Packages ship raw TypeScript through their exports maps. There is no per-package build step: the app lists them in
transpilePackages and Next.js compiles them together with the app.
Directoryapps/
Directorystorefront/ the Next.js app (
@welabs/retail-storefront) and the home of the Composition RootDirectoryapp/ routes; every page sits under the
[locale]segment- …
Directorycomponents/ app components
- …
Directoryfeatures/ Server Actions and feature islands (checkout, cart, reviews…)
- …
Directorylib/
Directorycommerce/ the Port’s entry point and the Composition Root (
adapters/index.ts)- …
Directoryserver/ thin server-only reads that thread auth and Locale
- …
Directoryseo/
PageSeo,pageMetadata(), robots rules, structured data- …
Directoryconfig/ brand and store identity, page content, Locales
- …
Directorymessages/ English source catalog plus translations
- …
Directorye2e/
Directorysmoke/ the Playwright smoke suite
- …
Directorypackages/
Directorycommerce-core/ canonical model, Capability interfaces, contract suite, bundled geo data
- …
Directoryadapter-woocommerce/ the only WooCommerce-aware code, identity and gateway dialects included
- …
Directoryadapter-woocommerce-invoice/ pure dialect for the PDF invoicing plugin (ADR 0009)
- …
Directoryadapter-fake/ in-memory adapter: Demo Mode engine and the contract suite’s reference
- …
Directorystorefront-ui/ shared presentational components and their message catalogs
- …
Directorytemplates/ Template Family registry: Home, Listing and Product templates plus a Shell Preset
- …
- CONTEXT.md the glossary (ubiquitous language)
Directorydocs/
Directoryadr/ architecture decision records
- …
| Package | npm name | Depends on (workspace) |
|---|---|---|
apps/storefront |
@welabs/retail-storefront |
every package below |
packages/templates |
@welabs/retail-templates |
storefront-ui, commerce-core |
packages/storefront-ui |
@welabs/retail-storefront-ui |
commerce-core |
packages/adapter-woocommerce |
@welabs/retail-adapter-woocommerce |
adapter-woocommerce-invoice, commerce-core |
packages/adapter-woocommerce-invoice |
@welabs/retail-adapter-woocommerce-invoice |
commerce-core |
packages/adapter-fake |
@welabs/retail-adapter-fake |
commerce-core |
packages/commerce-core |
@welabs/retail-commerce-core |
nothing |
Dependency direction
Section titled “Dependency direction” apps/storefront ──► templates ──► storefront-ui ──► commerce-core │ ▲ └──► Composition Root only ──► adapter-* ─────────┘commerce-coredepends on nothing. It defines the vocabulary everyone else speaks.- Presentation (
templates,storefront-uiand the app’s components) depends only oncommerce-coretypes. - Adapters depend only on
commerce-core.adapter-woocommercealso depends on the invoice dialect package, which stays pure: no HTTP calls, no auth. - Inside the app, exactly one module may name an adapter package:
lib/commerce/adapters/index.ts. ESLint enforces this withno-restricted-imports, and also forbids deep imports such as@welabs/retail-commerce-core/src/.... Tests ande2e/are the only other carve-out.
Everyday commands
Section titled “Everyday commands”pnpm installpnpm dev # the storefront; Demo Mode unless COMMERCE_SOURCE says otherwisepnpm typecheck # strict TypeScript across every workspacepnpm lint # includes the architecture-boundary and RTL rulespnpm test # Vitest: the contract suite against the Fake Adapter (hermetic)pnpm test:e2e # Playwright smoke suite in Demo Mode (stop pnpm dev first)pnpm buildThe root package.json pins pnpm and requires Node 22 or newer. If an older Node is first on your PATH, the build fails with
syntax errors; put a current Node first.