1. Current state
DI Commerce is Tag's B2B ordering platform on Adobe Commerce. The engineering team built sophisticated capabilities: multi-ship checkout handling thousands of addresses via CSV upload, tiered approval workflows with item-level granularity and delegation, queue-based asynchronous order processing. These are not trivial achievements. The platform handles complex B2B workflows that most commerce solutions can't touch.
The challenge is scale. Each new client engagement requires significant custom frontend development to deliver the same caliber of experience. The implementation process includes extended manual configuration phases, and each engagement is independent. The work done for one client doesn't carry over to the next. Effort scales linearly with each new client.
This creates a compounding problem as the commerce practice grows. Each new client in the pipeline represents the same cycle: custom development, manual configuration, independent timelines. The capabilities are there. The delivery mechanism doesn't scale.
The same challenge exists within a single client. A global program like ELC doesn't need one storefront. It needs many. Different markets, different regions, different branding, different pricing, different regulatory requirements. Under the current approach, each market is its own engagement. Under the modular approach, each market is a configuration.
2. The north star
Every architectural decision in this document serves one person: the field representative placing orders for their territory. They don't care about modules or configuration surfaces. They care about execution. Find the product, know what it costs, get it to the right stores, track that it arrived.
The field rep isn't shopping. They're distributing. They usually know what their territory needs. The platform's job is to make the path from "I know what my stores need" to "it's on its way" as short as possible. Every click that isn't serving that path is friction.
The primary mode is execution: "I need the Q2 counter display at 85 stores in the Southeast." The secondary mode is discovery: "What's available in the FY25 Mac Evergreen program?" The platform supports both, but it's optimized for the first.
What good looks like
Vista Print is the benchmark. They're the third-largest commercial printer in the US, competing in B2B. Their buying experience is optimized for someone who knows what they want and needs to execute fast. That's our standard.
| Interaction | Target |
|---|---|
| Evaluate a product from the listing card | Under 10 seconds |
| Find any specification on the product detail page | Within one scroll |
| Place a routine order (known products, known address) | Under 3 minutes |
| Complete a 200-address multi-ship order | Under 10 minutes |
| Answer "where is my order?" from order history | Under 10 seconds |
| Upload artwork, preview, proof, and add to cart | Under 5 minutes |
How every module serves the north star
| Module | Serves the north star by... |
|---|---|
| Navigation | Getting the field rep to the right product fast: category, campaign, brand paths |
| Search | "I know the SKU": instant execution path |
| Catalog | Presenting products clearly so decisions happen in seconds, not minutes |
| Pricing | Showing the right price for this region immediately, no ambiguity |
| Ordering | Shortest path from cart to confirmed order. Address book, checkout, done. |
| Multi-Ship | One order, 200 locations, one action. Territory-wide distribution in minutes. |
| Approval | Authorization without blocking. Clear status, fast review, no dead ends. |
| Print on Demand | See exactly what will be printed before committing. No guesswork. |
| Analytics | Measuring whether the platform is actually fast enough, clear enough. |
Clean slate, not an extension of the current implementation. The modular architecture gives us the chance to design the right experience for every module from scratch. The new framework starts with what the field rep needs and works backward to the architecture.
3. The scaling story
The modular architecture doesn't just make client onboarding faster. It makes the entire commerce practice compound. Each deployment, whether it's a new client or a new market for an existing client, makes the next one faster.
The trajectory
ELC is a global program. It doesn't need one storefront. It needs many. Different markets, different regions, different branding, different pricing rules, different currencies, different regulatory requirements. The modular architecture handles this natively: each market is a configured Shell with the same modules, different config values.
| Deployment | What happens | Relative effort |
|---|---|---|
| First ELC region | Modules built alongside implementation. Shell, base, and optional modules configured for Global/NA/APAC. | Highest: the investment |
| Second ELC market | Modules exist. New Shell config (branding, currency, pricing rules). Market-specific catalog and rate card data loaded. | Significantly reduced |
| Fifth ELC market | Refined process. Team knows the checklist. Shell config + data load. | Routine |
| First non-ELC client | Modules already work for a global multi-region program. New Shell, same modules, different config. | Comparable to a new ELC market |
| Mature framework | Config-file deployment. CLI scaffolding. Build pipeline. | 30 days from contract to live |
The effort curve:
The first ELC region is where the modules get built. Every subsequent ELC market reuses those modules. By the time the fifth ELC market launches, the team has a refined, repeatable process. The first non-ELC client benefits from everything ELC's program taught us. The trajectory is measurable: each deployment generates data that makes the formula more accurate and the number smaller.
Before and after
| Dimension | Current approach | Modular approach |
|---|---|---|
| Starting point | Blank slate per client | Configured Shell + base modules = working storefront |
| Implementation | Custom development per engagement | Configuration from defined module fields |
| Effort model | Linear: each client is independent | Compounding: each deployment makes the next faster |
| Discovery | Open-ended requirements | Guided module selection |
| Analytics | No instrumentation | Baked into the base from day one |
| New market (same client) | Nearly the same effort as a new client | Shell config + market data |
| Product roadmap | Driven by next SOW | Module catalog: build once, deploy to all |
| RFP response | Slides and promises | Working demo storefront configured to prospect needs |
| Timeline predictability | Estimate that varies per client | Formula: Shell + base + optional modules + client data |
| Target | Roughly 18 weeks best case | 30 days at maturity |
4. The strategic case
Seven reasons the modular architecture investment is justified.
Engine vs experience layer
The engineering team built the commerce engine: multi-ship, approvals, PO processing, inventory, the full B2B workflow. That engine works. What doesn't exist is a composable experience layer that can present that engine differently for different clients and markets. This project builds that layer. The engine doesn't change. The experience adapts.
Modular architecture
The experience layer starts with a Shell (the branded container) and is composed of modules that live inside it. Base modules are present in every storefront. Optional modules extend per client need. Each module is a self-contained capability with a defined configuration surface. Without this, the rest of the strategy is aspirational. With it, it's mechanically real.
Bespoke through configuration
To the client: "We built this for you." Internally: "We configured this for you." The client gets a tailored commerce experience: their brand, their catalog, their pricing, their approval workflows. They don't know it was assembled from modules. They experience a platform built for their business. Adding capabilities over time is enabling a module, not a new project.
Scale and predictability
Each client engagement builds modules that every subsequent client gets for free. Each ELC market builds process knowledge that the next market gets for free. The timeline becomes a formula, not an estimate. The formula improves with every deployment.
Innovation leverage
New capabilities get developed once and deployed to any client. AI-powered conversational search, smart reordering, visual search: each becomes a premium module that plugs into the Shell. Clients can add capabilities over time without a new SOW. The architecture supports bring-your-own-API-key patterns for AI capabilities.
Demo velocity
Tag maintains a pre-configured demo storefront with all modules active and demo products loaded. Going into an RFP, Tag configures the demo to match the prospect's needs and shows a working storefront, not slides. This collapses the pre-sales cycle and de-risks the implementation promise.
Product roadmap discipline
The product team's roadmap becomes the module catalog. "This quarter we're building the Print on Demand module and the Demand Capture module." Those aren't client-specific deliverables. They're product investments serving the entire portfolio. Bug fix once, deploy everywhere. Feature requests get evaluated as "does this become a config option or a new module?" The one-offs become visible exceptions rather than the default.
5. The architecture
The Shell
The Shell is the configured container that all modules live inside. It is not a module. The Shell provides branding (logo, colors, fonts, design tokens), layout zones (header, content area, footer), and application-level navigation (account menu: My Orders, Address Book, My Approvals, etc.). Active modules register their navigation links dynamically.
Each client market gets its own Shell configuration. ELC North America and ELC APAC share the same modules but have different Shell configs: different branding, different currency, potentially different layout preferences. The Shell is the first thing configured for each market.
Module tiers
Base package (every client, every market)
| Module | Purpose |
|---|---|
| Navigation | Structured browse paths: category, campaign collection, brand |
| Catalog | Product presentation, listings, filters, sort, compare, wishlist |
| Pricing | Price display, regional context, tier pricing, currency |
| Ordering | Full order lifecycle: cart, checkout, history, tracking, reorder, address book |
| Search | Product search: keyword, autocomplete, results |
| Analytics | Event pipeline, instrumentation across all modules |
Optional modules (per client)
| Module | Purpose | Registers in Shell |
|---|---|---|
| Multi-Ship | Multi-address checkout, CSV upload, address groups | Address Lists |
| Approval | Business justification, tier approval, delegation | My Approvals |
| Print on Demand | Product customization, proofing, templates (PrintXpand) | My Print Jobs |
| Briefing | Custom request submission, tracking, quote-to-order | My Briefs |
| Demand Capture | Buying windows, availability, queue-for-next-window | n/a |
Platform modules (separate phase)
| Module | Purpose |
|---|---|
| SSO / Identity | Client HR system, user assignment, approval routing |
| DAM Integration | API pull from client DAM for product imagery |
| CAP Sync | Commerce-to-CAP bidirectional pricing sync |
| Punch Out | Procurement system integration |
Integration patterns
One-way handoff: Module A passes control to Module B. Navigation leads to Catalog. Catalog leads to Ordering via Add to Cart.
Injection: Optional module injects UI into a base module's flow via defined hook points. Approval injects business justification into checkout. Print on Demand injects the Customize button onto the product detail page.
Registration: Module announces its presence to a container. Active modules register navigation links into the Shell. Approval registers an Approval History tab into order detail.
6. Current state: codebase coupling
The diagram below maps actual coupling between DI Commerce codebase modules. Color-coded tags on each module show the type of coupling: core class replacements (red), window globals (orange), DOM/JS coupling (yellow), shared state (blue), and logic duplication (gray). The two green-bordered modules on the right follow the clean module standard. Click any module for details.
7. Full module catalog
Complete module breakdowns following the standard anatomy: purpose, ownership boundaries, configuration surface, API dependencies, module dependencies, current state, UX requirements, success criteria, and open questions. Click any module to expand.
NavigationBase
Purpose: The field rep finds products through structured browse paths that reflect how the client organizes their catalog. They can navigate by product category, by campaign collection, by brand, or by any other taxonomy the client defines. Navigation is the first thing the field rep interacts with after login.
Owns
- Primary navigation structure (top nav, sidebar, mobile drawer)
- Browse path definitions (category tree, campaign collections, brand listing)
- Navigation hierarchy (parent/child, depth levels, flyout/sidebar)
- Campaign collection browse (curated cross-category groupings)
- Brand browse as alternative entry point
- Breadcrumbs
- Active state indicators
- Mobile responsive navigation
- Navigation-level analytics events
Does not own
Product display, filtering, sorting, pagination (Catalog). Search bar, autocomplete, results (Search). Price display (Pricing). Product visibility by customer group (engine via SSO/Identity). Application-level navigation like account menu (Shell).
Configuration surface
Browse paths
| Setting | Type | Default | Description |
|---|---|---|---|
| browse_paths | structured | ["category"] | Active browse paths: category, campaign_collection, brand, plus client-defined |
| browse_path_order | structured | ["category","campaign_collection","brand"] | Display order in navigation |
| default_browse_path | string | "category" | Default browse path on landing |
Hierarchy
| Setting | Type | Default | Description |
|---|---|---|---|
| max_depth | number | 3 | Maximum navigation depth levels |
| navigation_style | enum | flyout | Sub-level presentation: flyout, sidebar, accordion |
| show_product_count | boolean | false | Display product count per category |
Campaign collections
| Setting | Type | Default | Description |
|---|---|---|---|
| campaign_collections_enabled | boolean | false | Whether campaign collections appear as a browse path |
| campaign_collection_display | enum | grid | Presentation: grid, list, carousel |
| show_collection_dates | boolean | true | Display campaign active dates |
Brand browse
| Setting | Type | Default | Description |
|---|---|---|---|
| brand_browse_enabled | boolean | false | Whether brand is a browse path |
| brand_display | enum | alphabetical | Organization: alphabetical, grid, featured_first |
Mobile
| Setting | Type | Default | Description |
|---|---|---|---|
| mobile_breakpoint | number | 768 | Pixel width for mobile nav activation |
| mobile_style | enum | drawer | Mobile presentation: drawer, overlay, accordion |
API dependencies
Reads: Category tree with hierarchy, campaign collection definitions, brand listing with metadata, navigation state for active user.
Writes: None. Navigation is read-only from the frontend.
Events: browse_path_selected, navigation_depth, breadcrumb_click
Module dependencies
Required: Catalog (Navigation leads to product listings).
Integration points: Search (parallel discovery, layout positioning). Analytics (emits browse and hierarchy events).
Current state
Key components: menu.js (885 lines, full jQuery UI Menu replacement), theme.js (440 lines, header cloning and mobile drawer), navigation LESS (400+ lines), DiCommerce_Theme (body class toggles from admin config).
Coupling: Tightly coupled. menu.js assumes specific DOM hierarchy and hardcoded data attributes. theme.js clones elements by class name and hardcodes breakpoints. Cross-module dependency on DiCommerce_Catalog helper.
Estimate: ~80% rebuild. Hardcoded DOM assumptions and global JS coupling make existing components unsuitable for modular architecture. Preservable: responsive breakpoint concept, hierarchy data model, general UX patterns.
UX requirements
Key flows: Initial landing (default browse path active, current campaigns featured). Browse by category (subcategories reveal, breadcrumbs update). Browse by campaign collection (cross-cutting view across categories). Browse by brand. Switch between browse paths seamlessly. Mobile navigation (responsive drawer, all paths accessible).
Key states: Empty (no categories configured), Loading (skeleton nav), Populated (normal), Error (fallback to Search). Edge cases: category with no products, expired campaign collections, single brand, very deep hierarchy, very wide top level.
Benchmark: Vista Print navigation is clean and multi-path. Browse by product type, use case, or industry. Subcategories use flyout with visual icons. Mobile collapses to drawer. Target: find any product within 3 clicks from homepage.
Success criteria
Functional: All browse paths render correctly. Hierarchy matches config. Mobile fully functional. Breadcrumbs accurate. Path switching preserves context.
Adoption: Browse path distribution (category vs campaign vs brand). Navigation depth (target: 3 or fewer clicks to products). Mobile completion rate. Breadcrumb usage frequency.
Open questions
- Does this config surface cover all navigation scenarios across the client portfolio?
- How are campaign collections managed? Admin, synced from external, or client config?
- Are there clients needing custom taxonomies beyond category, campaign, and brand?
- Should navigation be personalized beyond region?
- How should expired campaign collections be handled?
- What happens when a category has zero products?
CatalogBase
Purpose: The field rep sees products presented clearly with the information they need to make a decision: images, descriptions, specifications, availability, labels. They can view listings, compare products, save to wishlist, filter, sort, and drill into detail.
Owns
- Product listing pages (PLP): grid/list layout, product cards
- Product detail pages (PDP): images, description, specs, qty selector, add-to-cart
- Product card content: name, SKU, image, availability, labels
- Product labels/badges ("New", "Limited", "Seasonal")
- Filters and faceted navigation
- Sort controls
- Pagination
- Compare (side-by-side attribute comparison)
- Wishlist (save for later)
- Campaign collection definitions as data
- Product type presentation (fixed SKU vs customizable)
- Availability display
- Product images (gallery, zoom)
Does not own
How the field rep arrives (Navigation or Search). Price display (Pricing). Cart/checkout/ordering (Ordering). Requisition lists (Ordering). Print on Demand UI on customizable PDPs (Print on Demand). Product data import or admin (engine). Product visibility by customer group (engine via SSO/Identity).
Configuration surface
Product listing
| Setting | Type | Default | Description |
|---|---|---|---|
| default_view | enum | grid | Default listing layout: grid or list |
| allow_view_toggle | boolean | true | Field rep can switch views |
| products_per_page | number | 24 | Products per page |
| show_sku | boolean | true | SKU displayed on cards |
| show_availability | boolean | true | Stock indicators shown |
Product detail
| Setting | Type | Default | Description |
|---|---|---|---|
| image_gallery_enabled | boolean | true | Product image gallery on PDP |
| image_zoom_enabled | boolean | true | Zoom on product images |
| show_related_products | boolean | false | Related products on PDP |
| qty_selector_style | enum | input | Quantity selector: input, stepper, dropdown |
Filters
| Setting | Type | Default | Description |
|---|---|---|---|
| filterable_attributes | structured | [] | Which attributes appear as filters |
| filter_position | enum | sidebar | Where filters render: sidebar, top, drawer |
| show_active_filters | boolean | true | Active filter chips above results |
Compare and wishlist
| Setting | Type | Default | Description |
|---|---|---|---|
| compare_enabled | boolean | true | Product comparison available |
| compare_max_items | number | 4 | Max products in a comparison |
| wishlist_enabled | boolean | true | Wishlist functionality |
Labels and collections
| Setting | Type | Default | Description |
|---|---|---|---|
| labels_enabled | boolean | true | Product label badges displayed |
| campaign_collections_enabled | boolean | false | Campaign collection groupings active |
API dependencies
Reads: Product listing data (paginated, with attributes/images/availability/labels), product detail data (full record), filterable attribute definitions, campaign collection data, compare data, wishlist data.
Writes: Add/remove from compare, add/remove from wishlist, filter/sort state.
Events: product_viewed, product_listed, compare_initiated, wishlist_add/remove, filter_applied/removed, sort_changed
Module dependencies
Required: None (technically standalone, but always runs with Navigation, Search, Pricing).
Integration points: Navigation (passes category/collection/brand, Catalog renders listing). Search (passes query/results, Catalog renders). Pricing (renders prices within cards/PDP). Ordering ("Add to Cart" bridges to Ordering). Print on Demand (injects "Customize" on customizable PDPs). Analytics (emits product/filter/sort events).
Current state
Key components: DiCommerce_Catalog (71 files), DiCommerce_ProductList (12 files, AJAX refresh), DiCommerce_ProductLabel (10 files), DiCommerce_CustomerProductGroup (15 files, visibility by customer group), Manadev_LayeredNavigation (third-party, 4 sub-modules), DiCommerce_Stock (103 files, real-time stock display).
Coupling: High coupling between ProductList AJAX and Manadev. product-list-ajax.js (671 lines) depends on Manadev DOM selectors bidirectionally. list.phtml calls helpers directly. Stock reinitializes after every AJAX refresh.
Estimate: ~50% rebuild. Backend module structure is reasonable. Frontend glue (AJAX orchestrator, Manadev coupling, direct helper calls) needs rebuilding as clean scoped components.
UX requirements
Key flows: Browse a listing (grid/list, cards with key info). Filter products (instant, no full reload, active filter chips). View product detail (gallery, specs, qty, price, add-to-cart). Compare products (2-4 side by side). Save to wishlist. View campaign collection (cross-category listing).
Key states: Empty listing (meaningful message, alternative browse paths). Loading (skeleton cards). Populated (normal). Error (retry option). Edge cases: single product, no image (placeholder), long name (truncation), single filter option, all out of stock.
Benchmark: Vista Print listings are clean and information-dense without clutter. Cards show image, name, starting price, quick-select. Filtering is fast, no page reload. Target: evaluate a product in under 10 seconds from the card, find any spec on PDP within one scroll.
Success criteria
Functional: Listings render for all browse paths. Filters apply instantly. Compare aligns attributes. Wishlist persists across sessions. Labels display based on conditions. Collections show products regardless of category.
Adoption: Filter usage rate. Compare usage. Wishlist-to-cart conversion. Average time on PDP. Products viewed per session before cart.
Open questions
- What product attributes are commonly filterable? Does this vary by client?
- Should Manadev LayeredNavigation be replaced with native Magento?
- How do campaign collections get created/managed?
- Are there product types beyond fixed SKU and customizable?
- How should out-of-stock products display?
PricingBase
Purpose: The field rep sees prices relevant to them: their region, their quantity breaks, their currency. They never see prices for regions or tiers that don't apply. The price displayed reflects exactly what they'll pay based on who they are and how much they're ordering.
Owns
- Price display on PLP and PDP
- Tier pricing presentation (quantity break tables)
- Regional price resolution
- Currency display formatting
- Special/promotional price display
- Price display in cart and order summaries
- Tax display rules
Does not own
Product organization or display (Catalog). Cart/checkout/ordering (Ordering). Backend price calculation (engine). Region/group assignment (SSO/Identity). Price ingestion (CAP Sync). Approval thresholds (Approval). Shipping cost calculation (Ordering/Multi-Ship).
Configuration surface
Regional settings
| Setting | Type | Default | Description |
|---|---|---|---|
| regional_pricing_enabled | boolean | true | Prices vary by region |
| regions | structured | [] | Region definitions (ID, name, currency) |
| show_region_label | boolean | false | Display region name alongside prices |
Tier display
| Setting | Type | Default | Description |
|---|---|---|---|
| tier_pricing_enabled | boolean | true | Quantity break pricing shown |
| tier_display_format | enum | table | Presentation: table, inline, progressive |
| tier_count | number | 10 | Maximum pricing tiers |
| show_savings | boolean | true | Show "you save X%" at higher tiers |
Currency and tax
| Setting | Type | Default | Description |
|---|---|---|---|
| currency_code | string | USD | ISO 4217 currency code |
| symbol_position | enum | before | Symbol placement: before or after |
| tax_display_mode | enum | excluding | How tax is shown: including, excluding, both |
Visibility
| Setting | Type | Default | Description |
|---|---|---|---|
| require_login_for_prices | boolean | true | Prices hidden until authenticated |
| no_price_message | string | "Login to see pricing" | Message when prices hidden |
API dependencies
Reads: Product price data by customer group/region (resolved price with tiers, specials, tax). Customer group/region assignment. Tax rules.
Writes: None. Display-only from frontend.
Events: Price change notifications (low priority, for long sessions).
Module dependencies
Required: Catalog (prices attach to products).
Integration points: Ordering (consumes resolved prices for cart/checkout). Multi-Ship (per-address tax display). Analytics (pricing events).
Current state
Key components: DiCommerce_ConfigurableProduct (tax class fix), DiCommerce_Checkout (special price in minicart), DiCommerce_PurchaseOrder (totals excluding rejected items), DiCommerce_Multishipping (currency conversion fix).
Coupling: Low coupling. Cleanest area in the codebase. All pricing delegates to core Magento. Four plugins are small, targeted, independent.
Estimate: ~90% preserve. Backend logic carries forward as-is. Frontend display components are simple renders of price data.
UX requirements
Key flows: Browse with prices (each product shows base price for region, promotional prices with strikethrough). View tier pricing (quantity breaks on PDP, active tier highlights as qty changes). Cart pricing (resolved per-unit price, line totals, subtotal, tax per config).
Key states: Loading (placeholder, no layout shift). Populated (normal). Error (show no_price_message, not $0). Edge cases: no tier pricing, expired special price mid-session, product visible but unavailable in region.
Benchmark: Vista Print shows prices clearly at every touchpoint. Tier pricing as simple quantity-price table with current tier highlighted. Target: the field rep should never wonder "what's my price for this?"
Success criteria
Functional: Displayed prices match backend 100%. Regional isolation complete. Tier pricing updates dynamically. Tax display correct across all touchpoints.
Adoption: Pricing clarity in surveys. Support tickets related to pricing confusion decrease. Tier pricing engagement (orders above minimum tier).
Open questions
- Are there pricing models beyond regional + tier? Volume discounts, contract, negotiated?
- How does tax display work across regions?
- Multiple simultaneous price points ("your price" vs "list price")?
- How are price changes communicated mid-campaign?
OrderingBase
Purpose: The field rep places orders and manages them through their full lifecycle: cart, checkout, confirmation, tracking, history, reorder, cancellation. They maintain an address book of outlet locations and requisition lists for repeat purchasing.
Owns
- Cart (minicart, full cart, line items, totals)
- Checkout flow (base: address > shipping > payment > review > place)
- Checkout extensibility (hook points for optional modules)
- Order confirmation
- Order history (filtering, sorting, pagination)
- Master order view (multi-ship grouping)
- Company orders view
- Order detail (tabbed, extensible by optional modules)
- Shipment tracking
- Reorder from history
- Order cancellation
- Requisition lists
- Address book (browse, search, add, edit, delete, outlet validation)
- Address lookup (REST API)
- Outlet validation (configurable rules)
- Custom address fields
Does not own
Product browsing/display (Catalog). Product search (Search). Price display (Pricing). Wishlist (Catalog). Business justification (Approval injects). Multi-address checkout, CSV upload, address groups (Multi-Ship extends). Approval workflows (Approval). Print on Demand design data (Print on Demand attaches). Async PO queue processing (engine). Payment gateway integration (engine).
Configuration surface
Cart
| Setting | Type | Default | Description |
|---|---|---|---|
| minicart_enabled | boolean | true | Minicart in Shell header |
| minicart_max_items_display | number | 5 | Max items shown before "View Cart" |
| allow_qty_edit_in_cart | boolean | true | Quantities adjustable on cart page |
Checkout
| Setting | Type | Default | Description |
|---|---|---|---|
| checkout_steps | structured | ["shipping","payment","review"] | Steps in order. Optional modules register additional steps via hooks. |
| guest_checkout_enabled | boolean | false | Checkout without auth (B2B almost always no) |
| order_comment_enabled | boolean | false | Field rep can add order comment |
Outlet address
| Setting | Type | Default | Description |
|---|---|---|---|
| outlet_address_enabled | boolean | true | Outlet address search/selection in checkout |
| outlet_validation_enabled | boolean | false | Validation rules active |
| outlet_validation_numeric_only | boolean | false | Restrict outlet number to numeric |
Address book
| Setting | Type | Default | Description |
|---|---|---|---|
| address_book_enabled | boolean | true | Address book management page available |
| allow_field_rep_add_address | boolean | true | Field reps can add addresses |
| allow_field_rep_edit_address | boolean | true | Field reps can edit addresses |
| allow_field_rep_delete_address | boolean | false | Typically admin-only |
Order history
| Setting | Type | Default | Description |
|---|---|---|---|
| orders_per_page | number | 20 | Orders per page in history |
| show_master_order_view | boolean | true | Multi-ship grouped under master |
| show_company_orders | boolean | false | See other company members' orders |
Order detail and actions
| Setting | Type | Default | Description |
|---|---|---|---|
| detail_tabs | structured | ["items","shipments","info"] | Tabs on detail page. Optional modules can register additional tabs. |
| show_reorder_button | boolean | true | Reorder from past orders |
| cancellation_enabled | boolean | true | Order cancellation available |
| requisition_lists_enabled | boolean | true | Saved product lists for repeat ordering |
API dependencies
Reads: Cart data, checkout config, outlet address search results, order history, master order data, company orders, order detail, shipment tracking, requisition lists, address book data, validation results.
Writes: Cart ops (add/update/remove), place order, outlet address selection, cancel order, requisition list ops, reorder, address book ops (add/edit/delete with validation).
Events: add_to_cart, cart_viewed, checkout_started, checkout_step_completed, order_placed, order_viewed, order_cancelled, reorder_initiated, requisition_list_created/ordered, shipment_tracked, address_added/edited/deleted, address_validated
Module dependencies
Required: Catalog (products to add to cart). Pricing (resolved prices for totals).
Integration points: Approval (injects business justification via hooks, registers Approval History tab). Multi-Ship (transforms checkout into multi-address flow). Print on Demand (attaches design data to line items). Analytics (emits all ordering events). Shell (registers My Orders, Address Book, Requisition Lists).
Current state
Key components: DiCommerce_Checkout (33 files), DiCommerce_OutletCheckout (10 files, 800+ line address popup), DiCommerce_AddressLookup (21 files, clean REST API client), DiCommerce_AddressListManager (22 files, address CRUD), DiCommerce_OutletValidation (15 files, clean validation rules), DiCommerce_Sales (145 files, master order view, company orders, shipment tracking), DiCommerce_OrderHistorySearch (14 files), DiCommerce_RequisitionList (10 files). Theme: 40+ checkout override files.
Coupling: Very high in checkout: 7+ feature flags across 3 ConfigProviders, window globals, localStorage state sharing, 6+ RequireJS mixins. Business justification duplicated between Checkout and Multishipping (moves to Approval). Address popup coupled via window globals. Sales module is monolithic but less coupled.
Bright spots: AddressLookup is a clean REST API client. OutletValidation follows the target module pattern. RequisitionList is thin and focused.
Estimate: ~65% rebuild. Checkout overrides and Sales expansion are the bulk. AddressLookup and OutletValidation preserve as-is.
UX requirements
Key flows: Add to cart (minicart updates in Shell). View cart (editable quantities, design thumbnails if Print on Demand active). Base checkout (address > shipping > payment > review > place). Checkout variations compose: Multi-Ship replaces, Approval injects, Print on Demand attaches. Confirmation. Order history (filter, sort, master order grouping). Order detail (tabbed, extensible). Shipment tracking. Reorder. Requisition lists (create, manage, order from). Address book management (CRUD with outlet validation). Cancellation.
Key states: Cart empty/populated. Checkout loading/in-progress/error. Order placed. History empty/populated. Tracking unavailable. Reorder with unavailable items. Edge cases: 100+ item cart, 50+ shipments in master view, checkout timeout.
Benchmark: Vista Print checkout is streamlined with minimal steps. Order history clean with obvious filtering. Reorder is one click. Target: routine order in under 3 minutes. "Where is my stuff?" answered in under 10 seconds.
Success criteria
Functional: Add to cart works from PLP/PDP. Checkout completes through all steps. Hook points work (optional module steps inject when active, absent when not). Order history accurate. Master order view correct. Tracking accurate. Reorder handles unavailable items. Requisition lists persist. Cancellation updates status. Address book CRUD with validation.
Adoption: Cart-to-checkout conversion. Checkout completion rate. Average checkout time (target: under 3 minutes). Requisition list usage. Reorder rate. History search usage. Tracking engagement.
Open questions
- How does the checkout hook mechanism work technically in Phase 1?
- What payment methods are supported?
- Should requisition lists support scheduled reorder?
- What determines cancellation eligibility?
- How do checkout variations compose when multiple optional modules are active?
- Should order detail tabs be extensible by optional modules?
SearchBase
Purpose: The field rep types what they're looking for and gets results. Search is the unstructured counterpart to Navigation's structured browse paths. When the field rep knows what they want but doesn't know where it lives in the category tree, Search gets them there directly.
Owns
- Search bar (input field, placement, focus behavior)
- Autocomplete/typeahead (product and category suggestions)
- Search results page
- Search query handling (min characters, debounce)
- Recent searches
- "Did you mean" / spelling correction
- Search-level analytics events
Does not own
How products display in results (Catalog renders cards, filters, sort). Structured browse paths (Navigation). Search engine configuration (engine/OpenSearch). Price display (Pricing). Application navigation (Shell).
Configuration surface
| Setting | Type | Default | Description |
|---|---|---|---|
| search_bar_position | enum | header | Where search renders: header, nav_inline, below_nav |
| min_characters | number | 3 | Characters before search triggers |
| debounce_ms | number | 300 | Delay after typing before querying |
| autocomplete_enabled | boolean | true | Typeahead suggestions |
| autocomplete_max_results | number | 5 | Max suggestions |
| results_per_page | number | 24 | Products per page on results |
| show_did_you_mean | boolean | true | Spelling correction suggestions |
| recent_searches_enabled | boolean | true | Recent search history shown |
API dependencies
Reads: Search results (product data with relevance ranking), autocomplete suggestions, spelling corrections.
Writes: Search query submission, recent search history (may be client-side).
Events: search_submitted, search_autocomplete_selected, search_zero_results (critical for catalog gap identification), search_result_clicked
Module dependencies
Required: Catalog (renders product cards in search results).
Integration points: Navigation (parallel discovery, layout coordination via Shell). Pricing (prices in autocomplete and results). Analytics (search events, zero-result tracking).
Current state
Key components: Manadev_LayeredNavigation (search integrated with layered nav), DiCommerce_ProductList (AJAX search results via same orchestrator as category pages), theme search templates and form-mini-mixin.
Coupling: Coupled to Manadev through shared ProductList AJAX mechanism. No standalone search component exists.
Estimate: ~60% rebuild. Search input is simple and preservable. Results rendering is entangled with ProductList/Manadev coupling. Backend OpenSearch integration stays as-is.
UX requirements
Key flows: Quick search (type, autocomplete, click suggestion or submit). Full results (Catalog listing components). Zero results (helpful message, suggestions, recent searches). Recent searches on focus.
Benchmark: Vista Print search is fast and forgiving. Autocomplete shows products with images immediately. Typos corrected. Target: find what you're looking for in one attempt 90%+ of the time.
Success criteria
Functional: Relevant results for names, SKUs, descriptions, attributes. Autocomplete within debounce window. Zero-result pages offer paths forward. Works across devices. Spelling correction activates.
Adoption: Search vs browse ratio. Zero-result rate. Autocomplete click-through rate. Search-to-cart rate.
Open questions
- Should search support searching within a category or brand?
- What search engine long-term? Native OpenSearch or dedicated service?
- What does the AI-powered search premium module look like?
AnalyticsBase
Purpose: Every interaction is tracked, measured, and available for analysis. The field rep doesn't see or interact with Analytics directly. It operates silently behind every other module, providing the event pipeline that all modules emit into.
Owns
- Event pipeline (mechanism for all modules to emit events)
- Event schema (standardized format)
- Provider integration (GA4, Adobe Analytics, or other)
- Consent management (opt-in/opt-out per legal requirements)
- Page-level tracking (views, session, device)
- Event forwarding to analytics destinations
- Analytics admin config
Does not own
What events get emitted (each module defines its own). Reporting dashboards (analytics platform). Business intelligence (out of scope). User identity resolution (SSO/Identity).
Configuration surface
| Setting | Type | Default | Description |
|---|---|---|---|
| provider | enum | google_analytics | Platform: google_analytics, adobe_analytics, custom |
| tracking_id | string | null | Provider tracking/measurement ID |
| consent_required | boolean | false | User consent required before tracking |
| consent_mode | enum | opt_out | Consent: opt_in (track after consent) or opt_out (track until declined) |
| track_page_views | boolean | true | Basic page view tracking |
| debug_mode | boolean | false | Events logged to console |
| event_batching | boolean | true | Batch events before sending |
| batch_interval_ms | number | 2000 | Milliseconds between batch sends |
API dependencies
Reads: User context (region, role, customer group from session).
Writes: Event dispatch to configured provider (client-side).
Events: Analytics doesn't emit events. It receives them. All other modules emit into the pipeline.
Module dependencies
Required: None. Provides the pipeline; other modules emit into it.
Integration points: Every module. Navigation (browse events), Catalog (product/filter events), Pricing (price events), Ordering (cart/checkout/order events), Search (query/zero-result events). Optional modules emit their own events when active.
Current state
Key components: Does not exist. CSP whitelist includes GA and Adobe DTM domains, but no actual event tracking implementation exists. No analytics JS, no data layer, no tag manager integration.
Estimate: 100% net-new.
UX requirements
No direct user-facing flows. Technical flow: page loads, Analytics initializes, checks consent, begins capturing, listens for module events, batches, dispatches. Analytics failures must never affect storefront functionality.
Benchmark: Operational: every client instrumented from day one, data flowing within 24 hours, success criteria for all modules have data within the first week.
Success criteria
Functional: Loads on every page under 50ms. Events from all modules captured and dispatched. Consent management works correctly. Failures never block storefront. Schema consistent across all modules.
Adoption: Measured indirectly. Success = are the criteria for all other modules measurable? Data completeness. Time to data. Event coverage.
Open questions
- Which providers supported? GA4, Adobe Analytics, both?
- What consent management approach?
- Event naming convention standardization?
- Privacy/legal requirements per region?
Multi-ShipOptional
Purpose: The field rep ships one order to multiple outlet locations: 10, 50, 200+ stores in a single checkout. They select outlets from the address book or upload via CSV, assign items to each address, and submit a single master order split into individual shipments per location.
Owns
- Multi-ship checkout variation (replaces single-address checkout)
- Multi-address selection (DataTables grid, search, sort, filter)
- CSV/XLSX address upload (parse, validate, add to address book)
- Per-address item assignment (default all-to-all, override per address)
- Master order creation (single order grouping all shipments)
- Address group management (save/load groups for repeat orders)
- Address autocomplete (ShipperHQ, coded but not activated)
- Multi-ship progress indicator
Does not own
Address book itself (browse, search, CRUD, validation) belongs to Ordering. Address lookup API (Ordering). Outlet validation rules (Ordering). Base checkout flow (Ordering). Master order display in history (Ordering displays; Multi-Ship creates). Business justification (Approval injects). Async PO queue processing (engine). Admin address pre-loading (engine). Price display (Pricing).
Configuration surface
Checkout
| Setting | Type | Default | Description |
|---|---|---|---|
| multi_ship_enabled | boolean | false | Replaces single-address checkout when on |
| max_addresses | number | 500 | Max ship-to addresses per order |
| default_assignment | enum | all_to_all | Default: all_to_all or manual |
Address selection grid
| Setting | Type | Default | Description |
|---|---|---|---|
| grid_page_size | number | 100 | Addresses per page |
| grid_searchable | boolean | true | Search in address grid |
| show_select_all | boolean | true | "Select All" available |
| show_region_filter | boolean | true | Filter by region/state |
CSV upload
| Setting | Type | Default | Description |
|---|---|---|---|
| csv_upload_enabled | boolean | true | CSV/XLSX upload available |
| csv_max_rows | number | 5000 | Max rows in upload |
| csv_template_download | boolean | true | Downloadable CSV template |
Address groups and processing
| Setting | Type | Default | Description |
|---|---|---|---|
| address_groups_enabled | boolean | true | Saved address groups |
| async_processing | boolean | true | Async PO creation |
| batch_size | number | 20 | Addresses per batch |
API dependencies
Reads: Address book data (from Ordering), address group data, shipping methods per address.
Writes: CSV address import, save address group, place master order, per-address item assignment.
Events: multiship_started, multiship_addresses_selected, multiship_csv_uploaded, multiship_address_group_used, multiship_assignment_changed, multiship_order_placed
Module dependencies
Required: Ordering (checkout variation, address book, cart, order infrastructure). Catalog (products). Pricing (per-address totals).
Integration points: Approval (business justification injects into multi-ship flow). Print on Demand (design data replication per address). Analytics (multi-ship events). Shell (registers "Address Lists").
Current state
Key components: DiCommerce_Multishipping (180 files, largest frontend footprint). 14 PHTML templates, 25 JS files, 11 controllers. DataTables address grid, CSV upload with bundled xlsx.js, business justification (duplicated, moves to Approval), shipping/overview mixins, address autocomplete (ShipperHQ, coded not activated). Replaces core Magento class via DI preference (highest-risk coupling). 8 async PO queue consumers.
Coupling: Hardest area. Bidirectional coupling with PurchaseOrder. Core class replacement creates upgrade risk. Business justification duplicated. localStorage caching. DataTables and xlsx bundled directly.
Estimate: ~75% rebuild. CSV upload and DataTables concept preservable. DI preference, business justification duplication, global coupling all need rebuilding.
UX requirements
Key flows: Initiate multi-ship (progress bar shows steps). Select addresses from book (DataTables grid with search/sort/filter, select all, selection count). Select from saved group (pre-select group addresses). CSV upload (parse, validate, summary of valid/invalid). Assign items (default all-to-all, override per address). Business justification (Approval injects). Review (summary stats + scrollable detail). Place master order (async PO creation). Track (master order in history, per-address shipment status). Manage address groups.
Key states: Address selection (empty/loading/populated/selected). CSV (processing/complete/failed). Assignment (default/custom). Review (summary). Processing (async). Error at each step.
Benchmark: Vista Print multi-recipient flows. Clean address management, fast bulk selection, scannable review. Target: 200-address order in under 10 minutes. Default all-to-all under 5 minutes.
Success criteria
Functional: Completes for 1-500 addresses. CSV parses and validates correctly. Assignment works for both default and custom. Master order groups correctly and triggers async PO. Address groups persist. Grid performant at 500 addresses. Composes with Approval and Print on Demand.
Effectiveness: Average checkout time (target: under 10 min for 200 addresses). CSV vs manual selection ratio. Address group reuse rate. Assignment override rate. Abandonment by step. CSV error rate. Addresses per order distribution.
Open questions
- Ideal address selection UX for 200+ addresses? Map-based, tree/hierarchy, search-first?
- Per-address item assignment at scale: exceptions-based or explicit?
- Should CSV support address updates (upsert) or only adding new?
- How do address groups relate to org structure?
- DI preference on core Magento class: Phase 1 resolution strategy?
- Should review include "download summary" for 200+ addresses?
ApprovalOptional
Purpose: Orders above a configured threshold require approval before fulfillment. The requester provides business justification during checkout. The approver reviews, approves or rejects at order or item level, and can delegate. Rejected orders can be revised and resubmitted.
Owns
- Business justification injection (single source, injects into both base and Multi-Ship checkout)
- Approval routing (consumes HR mapping from SSO/Identity)
- My Approvals dashboard (approver queue)
- Order-level approve/reject
- Item-level approve/reject with mass actions
- Tier-based sequential approval (Tier 1 before Tier 2)
- Rejection with required reason + resubmission
- Delegation (temporary transfer of authority)
- Auto-rejection (configurable timeout via cron)
- Approval status visibility (requester sees tier, approver, time pending)
- Approval history (audit trail, registers as tab in order detail)
- Notifications (pending, approved, rejected, delegation expiry)
Does not own
Checkout flow (Ordering provides hooks). Multi-ship flow (Multi-Ship). Cart/order placement/history/detail layout (Ordering). PO creation (engine). Master order grouping (Ordering displays, Multi-Ship creates). Approver assignment and org hierarchy (SSO/Identity from HR system). Price display (Pricing).
Configuration surface
Approval rules
| Setting | Type | Default | Description |
|---|---|---|---|
| approval_enabled | boolean | false | Approval workflow active |
| approval_tiers | structured | [] | Tier definitions: threshold + approval level. Sequential. |
| auto_approve_below | number | 0 | Orders below this value auto-approved |
| item_level_approval_enabled | boolean | false | Approve/reject individual items |
Business justification
| Setting | Type | Default | Description |
|---|---|---|---|
| justification_required | boolean | true | Justification required during checkout |
| justification_format | enum | both | Format: predefined, freeform, both |
| justification_categories | structured | [] | Predefined categories (e.g., Seasonal campaign, New store) |
| justification_file_upload | boolean | false | Supporting document attachments |
Rejection, delegation, auto-rejection
| Setting | Type | Default | Description |
|---|---|---|---|
| resubmission_enabled | boolean | true | Revise and resubmit rejected orders |
| rejection_comment_required | boolean | true | Approver must provide rejection reason |
| delegation_enabled | boolean | true | Approvers can delegate authority |
| delegation_max_duration_days | number | 30 | Maximum delegation duration |
| auto_rejection_enabled | boolean | false | Auto-reject after timeout |
| auto_rejection_days | number | 14 | Days before auto-rejection |
API dependencies
Reads: Pending approvals, approval history, approval rules, approver assignment (from HR via SSO/Identity), delegation status, order data.
Writes: Approve/reject order, approve/reject items, resubmit, create/revoke delegation, submit business justification.
Events: approval_required, order_approved, order_rejected, order_resubmitted, item_approved/rejected, delegation_created/expired, justification_submitted, auto_rejection_triggered, approval_time
Module dependencies
Required: Ordering (injects into checkout, manages approval status on orders).
Integration points: Multi-Ship (justification injects into multi-ship flow; master order approved as a whole). Ordering (Approval History tab in order detail). Print on Demand (design thumbnails visible in approval review). Analytics (approval events). Shell (registers "My Approvals"). SSO/Identity (provides approver mapping).
Current state
Key components: DiCommerce_PurchaseOrder (437 files, 8 core Magento PO classes replaced via DI preferences, 49 templates, 15 layouts, 3 UI components). DiCommerce_PurchaseOrderItem (104 files, item-level grid with mass actions). DiCommerce_PurchaseOrderRule (24 files, thin rule extension). DiCommerce_Company (118 files, approval-related: tier config, role mappings, delegation system). Business justification duplicated between Checkout and Multishipping.
Coupling: High coupling in PO/Multi-Ship/Company triangle. 8 DI preference class replacements (high upgrade risk). Business justification duplicated (consolidates here). Role name string coupling is fragile.
Bright spots: PoDraft is standalone. PurchaseOrderRule is thin. Delegation system is self-contained. ViewModel pattern (RoleInfo, ApprovalProducts) is clean.
Estimate: ~60% rebuild. DI preferences need plugin-based replacement. Business justification consolidates. Delegation preservable. UI component grids need scoping. Role name coupling replaced with HR-based assignment.
UX requirements
Requester flows: Business justification during checkout (categories + text + files). Order pending approval (status with tier, approver, time). Order approved (notification, status update). Order rejected (notification with reason, "Revise and Resubmit" visible). Revise and resubmit (modify and resubmit, full audit trail). Track approval status in history.
Approver flows: My Approvals dashboard (pending orders, filterable, urgent highlighted). Review order (full details + justification + attachments; master orders for Multi-Ship). Approve (with optional comment). Reject (with required reason). Item-level approve/reject with mass actions. Delegate authority (date range, expiry warning). Manage delegations.
Benchmark: Approver should review and act in under 2 minutes. Requester should always know where their order is and why it was rejected. Revise-and-resubmit should be as fast as modifying a cart.
Success criteria
Functional: Justification injects correctly into both checkout flows. Orders route to correct approver. Actions update status and trigger notifications. Rejection reason visible. Resubmit works. Item-level handles partial approval. Delegation works with expiry. Auto-rejection triggers. Composes with Multi-Ship.
Effectiveness: Average approval time (target: under 24 hours). Rejection rate. Resubmission rate (healthy = flow works). Auto-rejection rate (high = approvers not reviewing). Item-level usage. Delegation usage. Queue depth per approver.
Open questions
- On resubmission, does approval start from Tier 1 or resume at rejecting tier?
- What predefined justification categories are needed?
- How does HR integration provide approver mapping? Periodic sync or real-time lookup?
- What about partially approved items in multi-ship master orders?
- Phase 1 resolution for the 8 DI preference class replacements?
Print on DemandOptional
Purpose: The field rep customizes products with their own artwork: uploading designs, placing them on templates, previewing what the finished product looks like with fold lines/bleed/safe zones, and proofing before ordering. Powered by PrintXpand integration.
The contract confirms B2B template governance (per-customer and per-customer-group assignment), brand compliance validation (node-level locking, DPI validation, prevention of unauthorized modifications), SVG-to-PDF rendering up to 240x22" at 300 DPI, and S3 delivery of production files.
Owns
- Product designer experience (powered by PrintXpand)
- Template library (per product, with design zones, bleed, fold, safe)
- Interactive viewer (2D/3D, fold lines, bleed zones, safe zones)
- Artwork upload (drag-drop, file validation)
- Design tools (text, color, shapes, clipart, constrained to brand palette/fonts)
- Proofing flow (high-res preview, approve/reject before cart)
- Dynamic pricing (per-element, live updates during design)
- Print on Demand status tracking and My Print Jobs
- "Customize" button injection on PDP
- Design data in cart/checkout (via PrintXpand observers)
- Production-ready output (PDF/PNG at 300 DPI, CMYK)
Does not own
PDP layout (Catalog). Cart/checkout/order lifecycle (Ordering). Base pricing (Pricing). Template creation (PrintXpand admin). DAM for artwork assets (platform module). Production fulfillment (engine).
Configuration surface
Templates and tools
| Setting | Type | Default | Description |
|---|---|---|---|
| enable_product_designer | boolean | false | Per-product toggle for "Customize" button |
| template_library_enabled | boolean | true | Pre-designed templates available |
| text_tool_enabled | boolean | true | Text placement |
| clipart_enabled | boolean | true | Clipart library |
| image_upload_enabled | boolean | true | Artwork file upload |
| brand_color_palette | structured | [] | Brand-approved colors (restricts available palette) |
| font_library | structured | [] | Available fonts (Google Fonts + custom .ttf) |
Viewer
| Setting | Type | Default | Description |
|---|---|---|---|
| show_fold_lines | boolean | true | Fold line overlays |
| show_bleed_zone | boolean | true | Bleed area highlighting |
| show_safe_zone | boolean | true | Safe zone highlighting |
| enable_3d_preview | boolean | false | 3D rotatable preview (requires model) |
Proofing and pricing
| Setting | Type | Default | Description |
|---|---|---|---|
| proofing_required | boolean | true | Proof approval required before ordering |
| max_proofing_rounds | number | 2 | Max proof iterations |
| auto_approve_reorders | boolean | false | Reorders of approved artwork skip proofing |
| dynamic_pricing_enabled | boolean | false | Price adjusts based on customization |
| allow_artwork_reuse | boolean | true | Reuse previously approved designs |
API dependencies
Reads: Template library (from PrintXpand), submission data and statuses, production status, past artwork for reuse.
Writes: Upload artwork, save design, submit for proofing, approve/reject proof.
Events: artwork_uploaded, template_selected, viewer_interaction, proof_submitted, proof_approved, proof_rejected, artwork_reused, design_completed
Module dependencies
Required: Catalog ("Customize" injects into PDP). Ordering (design data flows into cart/checkout).
Integration points: Pricing (base price + customization surcharge = total, two layers). Approval (proofing is pre-cart, business justification is post-cart, no conflict). Multi-Ship (design data must replicate per address). Analytics (design events). Shell (registers "My Print Jobs").
Current state
Key components: Does not exist in current codebase. PrintXpand integration is being built by the engineering team. The work has not landed in staging yet.
What PrintXpand provides (~80%): HTML5 canvas editor, admin template management, SVG-based design zones, bleed/cut/safe lines, design tools (text, images, clipart, shapes), per-element dynamic pricing, 2D/3D preview, print-ready output (PDF/PNG/CF2/DDES/DXF, CMYK), cart integration via Magento observers, full-screen editing, multi-language, printable color restrictions.
What we build around it (~20%): Shell registration (My Print Jobs), analytics event emission, proofing workflow verification, B2B template governance verification (contract confirms it's in scope), multi-ship design replication, checkout flow integration testing, CSP whitelisting, production routing.
UX requirements
Key flows: Select customizable product (PDP shows "Customize"). Enter designer (PrintXpand editor, template selection). Upload artwork (drag-drop, validation). Interactive preview (fold/bleed/safe overlays, zoom, rotate, 3D). Design tools (text, colors, clipart constrained to brand). Dynamic pricing (live updates). Submit for proofing (high-res preview). Add to cart (design thumbnail on line item). Track status (My Print Jobs). Reuse artwork on new orders.
Key states: No customizable products (dormant). Designer loading. Template selection. Upload in progress/failed. Design active. Proofing in progress/ready/rejected/approved. In production. Error.
Benchmark: Vista Print. Interactive template viewer with fold/bleed/safe, live preview, zoom/rotate, 3D, clear proofing. Target: upload, preview, proof in under 5 minutes. Never wonder "will this look right?"
Success criteria
Functional: Editor loads reliably. Upload validates correctly. Viewer renders accurately with fold/bleed/safe. Proofing matches final output. Design data flows through cart/checkout/multi-ship. Production files generated with CMYK accuracy. Dynamic pricing correct.
Adoption: Customization completion rate (click "Customize" to cart). Proof approval rate by round. Artwork reuse rate. Time to completion (target: under 5 min upload, under 10 min design tools). Upload failure rate. Design tool engagement.
Open questions
- PrintXpand integration status: what's built, what's remaining?
- Magento 2.4.8-p3 compatibility verified?
- How does design data attach to cart items? Critical for multi-ship replication.
- Does PrintXpand proofing meet the pre-order approval requirement?
- Per-customer-group template restrictions needed?
- Production routing pipeline: manual download or automated?
8. Module boundaries
Every capability in the storefront belongs to exactly one module. When two modules touch, that's an integration point: a defined handoff, not shared ownership. Clear boundaries prevent the coupling issues that made the current implementation difficult to scale.
Click any module for boundary detail: what it owns, what it does not own, and where it connects to other modules.
Key boundary decisions
| Decision | Owner | Rationale |
|---|---|---|
| Address book | Ordering (base) | Even single-ship clients use it. Multi-Ship extends with bulk operations but doesn't own it. |
| Wishlist vs requisition lists | Wishlist = Catalog, Requisition = Ordering | Wishlist is browsing (interested). Requisition lists are action (committed to repeat ordering). |
| Business justification | Approval (optional) | Single source. Injects into both base and Multi-Ship checkout. No duplication. |
| Approval routing | Approval, consuming SSO/Identity | Org hierarchy from client HR system. No self-approval. Approval applies rules; it doesn't define the org chart. |
| Filters and sort | Catalog | Operate on product attributes within a listing. Not Navigation, not Search. |
| Search | Own base module | Different pattern from Navigation. Creates extension path to AI search. |
| Campaign collections | Catalog = data, Navigation = browse path | Collection is a product grouping (Catalog). Nav link to it is a browse path (Navigation). |
| Master order display | Ordering displays, Multi-Ship creates | Multi-Ship creates grouped data. Ordering renders it in history/detail. |
| Customization pricing | Print on Demand (PrintXpand) | Base price from Pricing + surcharge from PrintXpand. Two layers, no conflict. |
| Rejected orders | Approval: revise and resubmit | Requester sees reason, modifies, resubmits. Not a dead end. |
Boundary diagrams
Click any module in the architecture diagram below for boundary detail.
9. Two-phase approach
Phase 1: Foundation
Rebuild the experience layer as clean, well-bounded Adobe Commerce modules within the existing Magento stack. Each module follows a consistent standard: own admin config section scoped per website, data through defined interfaces, own scoped frontend components, no cross-module coupling.
What Phase 1 delivers
Clean, reusable modules across all client websites. Defined config surfaces per module so the implementation team knows exactly what to configure. Modules that don't break each other. A repeatable process: same checklist, same modules, same fields for every client and every market. Dramatically faster onboarding. And Phase 2 readiness, because every module is internally decoupled, so migrating to headless later is module-by-module.
What Phase 1 does not deliver
Config-file-driven deployment (it's admin panel config instead). CLI scaffolding (it's manual setup instead). The 30-day target (it's "dramatically faster" instead of a formula).
Phase 2: Acceleration
Migrate the clean Phase 1 modules into a headless frontend. The Shell becomes a deployable container. Client instances become config files consumed by a build pipeline. CLI scaffolding. 30-day deployment target as a formula, not an aspiration.
Phase 2 is only possible because Phase 1 produces modules with clean boundaries. There's nothing to migrate if the modules are still coupled. Phase 1 is the foundation that makes Phase 2 achievable.
Why Phase 1 first
Phase 1 is faster to deliver. It uses the stack the engineering team already knows. It produces measurable improvement immediately: the first ELC region benefits from Phase 1 modules. And it builds the clean boundaries that Phase 2 requires. Going straight to headless means building the Shell container, the composition layer, the API surfaces, and the modules all at once. Phase 1 is the investment that makes Phase 2 the acceleration.
10. Current state vs future state
The current implementation process includes extended phases of manual configuration work, with each client starting from scratch. Under the modular approach, each phase either compresses, stays manual but improves, or disappears entirely.
| Current phase | What it becomes |
|---|---|
| Site creation (manual environment provisioning) | Create a new Magento Website. Standardized process, same every time. |
| Site branding (custom CSS, iterative feedback) | Shell config: design tokens (logo, colors, fonts). Defined fields, not custom theme work. |
| Discovery (open-ended requirements gathering) | Guided module selection. "Here's the base. Which optional modules do you need?" Weeks become days. |
| DI CAP preparation (rate card, pricing sync) | Standardized data schema. Client provides data in a known format. Eventually automated via IngestIQ. |
| Commerce Configuration (the densest phase) | Walk through the module config checklist. Defined fields per module. The single biggest compression. |
| Config replication to production (manual UAT-to-LIVE) | Disappears. Per-website config scoping handles environments. |
| SSO (blocks the whole timeline if client IT is slow) | Platform module: can be added post-launch. Storefront goes live without it. |
| Punch Out (same client IT dependency) | Platform module: added when client IT is ready. Doesn't block launch. |
| UAT (testing custom code) | Testing validates configuration, not custom code. Fewer surprises. |
| Training (custom materials per client) | Standardized per module. Same training, different screenshots. |
11. Codebase reality
The existing codebase has been audited comprehensively. The platform runs Adobe Commerce 2.4.8-p3 Enterprise on Cloud with 37 custom modules. The engineering work is substantial. The preserve/rebuild estimates below reflect what it takes to bring each module up to the target standard: properly scoped boundaries, defined interfaces, and per-website configuration.
| Component | Estimate | Key finding |
|---|---|---|
| Navigation | ~80% rebuild | 885-line menu.js tightly coupled to theme |
| Catalog | ~50% rebuild | Backend reasonable; frontend glue (AJAX + Manadev coupling) needs rebuilding |
| Pricing | ~90% preserve | Cleanest area: 4 small plugins delegating to core Magento |
| Ordering | ~65% rebuild | 40+ checkout overrides, 145-file Sales module. Address lookup and outlet validation modules preserve as-is. |
| Search | ~60% rebuild | Coupled to Manadev LayeredNavigation |
| Analytics | 100% net-new | No existing instrumentation |
| Multi-Ship | ~75% rebuild | Hardest area. Core Magento class replacement. Business justification duplication. |
| Approval | ~60% rebuild | Spans 3 codebase modules. 8 DI preference class replacements. |
| Print on Demand | Integration | PrintXpand contract signed. ~20% custom build around it. |
Module standard
The target pattern for every module: own config section, own JavaScript, no plugins on other modules, no template overrides, integration via defined interfaces. Some modules in the current codebase already follow this pattern. Phase 1 brings the rest up to the same standard.
Key coupling issues to resolve
Window globals for cross-module communication. localStorage state sharing across checkout steps. Core Magento class replacements (DI preferences) creating upgrade risk. Direct helper calls in templates. DOM selector coupling between JavaScript modules. Feature flags scattered across multiple config providers. A single cacheable="false" attribute disabling full-page cache on every frontend page.
12. First implementation: ELC
ELC is a global program, not a single storefront. The first implementation covers three initial regions (Global, North America, APAC), with subsequent markets following as the framework matures.
Module selections
| Module | Tier | Status |
|---|---|---|
| Navigation | Base | ON category + campaign collection + brand |
| Catalog | Base | ON two product types (fixed SKU + customizable) |
| Pricing | Base | ON 3 regions, 10-tier, region-restricted |
| Ordering | Base | ON address book, requisition lists, master order view |
| Search | Base | ON standard with autocomplete |
| Analytics | Base | ON provider TBD, consent opt-in |
| Multi-Ship | Optional | ON CSV upload, address groups, async PO |
| Approval | Optional | ON tier thresholds TBD, HR-based routing |
| Print on Demand | Optional | ON PrintXpand, SVG templates, proofing |
| Briefing | Optional | TBD needs input |
| Demand Capture | Optional | TBD needs input |
Platform module phasing
| Module | Day 60 (Fixed SKU) | Day 90 (Bespoke) | Post-launch |
|---|---|---|---|
| DAM Integration | Active | Active | Active |
| CAP Sync | Active | Active | Active |
| SSO / Identity | Active | Active | Active |
| Punch Out | Deferred | TBD | Active |
Timeline milestones
| Milestone | Target | What's live |
|---|---|---|
| Shell + Discovery | Weeks 1-2 | Brand assets received, module configs confirmed, platform integrations initiated |
| Base configuration | Weeks 3-6 | All base modules configured, DAM/CAP/SSO integrations complete, catalog loaded |
| Optional modules + UAT | Weeks 7-8 | Multi-Ship and Approval configured, UAT with ELC users |
| Go-live: Fixed SKU | Week 9 (~Day 60) | Field reps live. Browse, search, price, order, multi-ship, approval, tracking. |
| Print on Demand | Weeks 10-13 | PrintXpand integration, templates created, proofing operational |
| Go-live: Bespoke | ~Day 90 | Customizable products with Print on Demand live |
Subsequent ELC markets
After the first three regions launch, each subsequent ELC market follows a compressed path. The modules are already built. The process is already refined.
New Shell configuration: Market branding, currency, language preferences. Defined fields.
Module configuration: Same modules, market-specific values. Pricing regions, tax rules, catalog subset, category structure.
Market data: Rate card, product catalog, outlet addresses for this market.
Platform connections: SSO for this market's users, DAM for market-specific imagery, CAP sync for market pricing.
For subsequent ELC markets, the bottleneck shifts from Tag development effort to ELC data readiness: rate card data, product catalog, outlet addresses, brand assets for that market, SSO configuration from ELC IT. Tag's configuration work compresses to days. The timeline is driven by how fast ELC can provide market-specific data.
13. What's next
| Priority | Status | Notes |
|---|---|---|
| Module catalog: base + Multi-Ship, Approval, Print on Demand | Complete (draft) | Full entries with config surfaces, boundaries, UX requirements |
| Module Boundary Map | Complete (draft) | Territory definitions, 12 boundary disputes resolved, integration patterns |
| ELC Implementation Specification | Complete (draft) | Shell + module configs + phasing + timeline |
| Module catalog: Briefing, Demand Capture | Needs input | Requires team discussion on requirements |
| Module standard document | Not started | Target pattern, anti-patterns, consistency checklist |
| ELC subsequent market playbook | Not started | Compressed process for new ELC markets |
| Adobe Commerce feasibility assessment | Not started | Per-module: what's native, extension, custom |
| Tag demo storefront | Not started | Pre-configured Shell with demo data for RFPs |
| Prototype scaffold | Not started | Light frontend validating the ELC module composition |
| Phase 2 roadmap | Not started | Headless migration path, API surface gap analysis |
14. Open questions
| Category | Question | Status |
|---|---|---|
| ELC | Approval tier thresholds: what dollar amounts trigger each tier? | Needed |
| ELC | Predefined justification categories | Needed |
| ELC | Auto-rejection policy: should orders auto-reject after timeout? | Needed |
| ELC | Item-level approval: needed, or is order-level sufficient? | Needed |
| ELC | Analytics provider preference: GA4 or Adobe Analytics? | Needed |
| ELC | Tax display rules per region: inclusive vs exclusive? | Needed |
| ELC | Brand assets (logo, colors, fonts, guidelines) | Needed |
| ELC | Which products will be customizable (Print on Demand)? | Needed |
| ELC | Outlet validation rules for address book? | Needed |
| ELC | Does ELC need Briefing? Demand Capture? | Discovery |
| Engineering | PrintXpand integration status: what's built, what's remaining? | Needed |
| Engineering | Magento 2.4.8-p3 compatibility with PrintXpand: verified? | Needed |
| Engineering | How does PrintXpand design data attach to cart items? | Needed |
| Engineering | DI preference class replacements (8 in PO, 1 in Multi-Ship): resolution strategy? | Needed |
| Engineering | Does PrintXpand proofing meet the pre-order approval requirement? | Needed |
| Product | Briefing module requirements: what should the workflow cover? | Needed |
| Product | Demand Capture requirements: buying window mechanics? | Needed |
| Architecture | Multi-Ship address selection: best UX for 200+ outlets? | Discussion |
| Architecture | Checkout hook mechanism in Phase 1 (Magento)? | Discussion |
| Architecture | How do checkout variations compose when multiple modules are active? | Discussion |
| Architecture | Per-address item assignment at scale: exceptions-based or explicit? | Discussion |
| Architecture | Config schema format: YAML, JSON? Build pipeline details? | Phase 2 |
| Architecture | API surface gap: which DiCommerce capabilities need new endpoints? | Phase 2 |
1. Client overview
ELC is a global program, not a single storefront. Different markets, different regions, different branding, pricing, currency, and regulatory requirements, each needing their own commerce experience. The modular architecture handles this natively: each market is a configured Shell with the same modules and different config values.
This spec defines the first ELC implementation (three initial regions) and the path to subsequent markets. The first region is the investment: modules built alongside the implementation. Every market after that reuses those modules. The compounding starts here.
| Parameter | Value |
|---|---|
| Client | Estee Lauder Companies (ELC) |
| Contract effective | April 1, 2026 |
| Program scope | Global multi-market, starting with 3 regions |
| Initial regions | Global, North America, APAC |
| Product types | Fixed SKU (standard evergreen) + Customizable (bespoke with Print on Demand) |
| Regional pricing | 4 prices per region, 10-tier quantity pricing per item |
| Timeline targets | Day 60 for fixed SKU, Day 90+ for bespoke with Print on Demand |
| Benchmark | Vista Print: the buying experience must match or exceed their UX |
2. The trajectory
| Deployment | What happens | Relative effort |
|---|---|---|
| First ELC region (Global/NA/APAC) | Modules built alongside implementation. Shell, base, and optional modules configured. | Highest: the investment |
| Second ELC market | Modules exist. New Shell config (branding, currency, pricing rules). Market-specific catalog and rate card data loaded. | Significantly reduced |
| Fifth ELC market | Refined process. Team knows the checklist. Shell config + data load. | Routine |
| First non-ELC client | Modules already work for a global multi-region program. New Shell, same modules, different config. | Comparable to a new ELC market |
| Mature framework | Config-file deployment. CLI scaffolding. Build pipeline. | 30 days from contract to live |
The first ELC region is where the modules get built. Every subsequent ELC market reuses those modules. By the time the fifth market launches, the team has a refined, repeatable process. The first non-ELC client benefits from everything ELC's program built.
3. Shell configuration
The ELC Shell is the branded container. ELC's visual identity applied to the storefront frame. Each ELC market gets its own Shell: same module composition, different branding and locale values.
| Setting | ELC value | Notes |
|---|---|---|
| client_name | Estee Lauder Companies | Displayed in Shell where applicable |
| logo_url | TBD | From ELC brand assets. May vary per market. |
| color_primary | TBD | From ELC brand guidelines |
| color_secondary | TBD | From ELC brand guidelines |
| font_primary | TBD | Headings, navigation, buttons |
| font_secondary | TBD | Body text |
| header_layout | standard | Logo, navigation, search, minicart, account menu |
| show_language_selector | false | English only at launch. Per-market Shell can enable later. |
| session_timeout_minutes | 60 | Standard timeout |
Shell account menu (auto-populated by active modules)
| Link | Source module | Active |
|---|---|---|
| My Orders | Ordering (base) | Always |
| Address Book | Ordering (base) | Always |
| Browse Products | Navigation (base) | Always |
| Address Lists | Multi-Ship (optional) | Yes |
| My Approvals | Approval (optional) | Yes |
| My Print Jobs | Print on Demand (optional) | Yes |
| Requisition Lists | Ordering (base, if enabled) | Yes |
4. Base module configurations
All six base modules are active for every client and every market. These are the ELC-specific config values for the initial three regions.
Navigation
Three browse paths: product category, campaign collection, and brand. Campaign collections are central to ELC's business: a collection like "FY25 Mac Evergreen" groups products across categories for a specific campaign.
| Setting | ELC value | Notes |
|---|---|---|
| browse_by_category | true | Primary browse path |
| browse_by_brand | true | MAC, Clinique, Estee Lauder, etc. |
| browse_by_campaign_collection | true | Core ELC workflow |
| category_depth | 3 | Category > subcategory > product type |
| mobile_nav_style | drawer | Hamburger with slide-out drawer |
| show_breadcrumbs | true |
Catalog
Two product types need distinct presentation: fixed SKU (standard items with images and specs) and customizable (items that show a "Customize" button for Print on Demand).
| Setting | ELC value | Notes |
|---|---|---|
| default_view | grid | Grid layout for product listings |
| allow_view_toggle | true | Field reps can switch to list view |
| products_per_page | 24 | |
| show_sku | true | SKU visible on product cards |
| show_availability | true | Stock indicators on listings |
| compare_enabled | true | Side-by-side product comparison |
| wishlist_enabled | true | Save for later |
| campaign_collections_enabled | true | Campaign collection groupings active |
| labels_enabled | true | Product labels ("New", "Seasonal", etc.) |
Pricing
Three regions with four regional prices each and 10-tier quantity breaks. The field rep is assigned to a region via SSO/Identity and sees only their region's prices. Subsequent ELC markets may introduce additional pricing regions without code changes.
| Setting | ELC value | Notes |
|---|---|---|
| regions | ["Global", "North America", "APAC"] | Three pricing regions. Subsequent markets add their own. |
| regional_prices_per_item | 4 | Four price points per region |
| tier_pricing_enabled | true | 10-tier quantity pricing |
| tier_count | 10 | Ten quantity break tiers per item |
| currency_display | Regional default | USD for NA, varies by APAC and Global |
| tax_display | TBD | Inclusive or exclusive, configurable per region |
| price_visibility | region_restricted | Field rep sees only their assigned region |
| show_tier_table | true | Tier pricing table visible on PDP |
Ordering
Standard checkout flow with address book. The base checkout handles single-address orders. Multi-Ship extends it for multi-address.
| Setting | ELC value | Notes |
|---|---|---|
| checkout_steps | ["shipping", "payment", "review"] | Approval injects business justification. Multi-Ship replaces address selection. |
| outlet_validation_enabled | true | Outlet validation active |
| address_book_enabled | true | Address book management page |
| allow_field_rep_add_address | true | Field reps can add addresses |
| allow_field_rep_edit_address | true | Field reps can edit addresses |
| allow_field_rep_delete_address | false | Admin-only deletion |
| show_master_order_view | true | Multi-ship orders grouped under master view |
| show_company_orders | true | Visibility into company-wide orders |
| requisition_lists_enabled | true | Saved product lists for repeat ordering |
| show_reorder_button | true | One-click reorder from history |
Search
Standard product search with autocomplete. Extension path to AI conversational search as a future premium module.
| Setting | ELC value | Notes |
|---|---|---|
| autocomplete_enabled | true | Typeahead suggestions |
| show_recent_searches | true | |
| min_characters | 2 | Search triggers after 2 characters |
| results_per_page | 24 | Matches Catalog listing |
Analytics
Every ELC interaction instrumented from day one. Data scoped per Magento website: each ELC market's analytics are independent but can be aggregated at the property level.
| Setting | ELC value | Notes |
|---|---|---|
| provider | TBD | GA4 or Adobe Analytics, client preference |
| tracking_id | TBD | ELC's analytics property ID |
| consent_required | true | GDPR for Global, CCPA for NA |
| consent_mode | opt_in | Track only after consent (GDPR compliance) |
5. Optional module selections
Multi-Ship ON
ELC field reps order to multiple retail locations per order. Multi-Ship replaces the single-address checkout with multi-address selection and master order creation.
| Setting | ELC value | Notes |
|---|---|---|
| max_addresses | 500 | Standard max |
| default_assignment | all_to_all | All items to all selected addresses |
| csv_upload_enabled | true | Bulk address upload via CSV/XLSX |
| csv_max_rows | 5000 | |
| address_groups_enabled | true | Saved address groups for repeat multi-ship |
| address_autocomplete_enabled | false | Evaluate ShipperHQ integration later |
| async_processing | true | Async PO creation for large orders |
| batch_size | 20 | Standard batch |
Approval ON
ELC orders require business justification and threshold-based approval. Routing comes from ELC's HR system via SSO/Identity.
| Setting | ELC value | Notes |
|---|---|---|
| approval_tiers | TBD | Tier thresholds from ELC. Expected: at least 2 tiers. |
| auto_approve_below | TBD | Orders below this value skip approval |
| item_level_approval_enabled | TBD | Approve/reject individual line items? |
| justification_required | true | Business justification required |
| justification_format | both | Predefined categories + freeform text |
| justification_categories | TBD | e.g. "Seasonal campaign", "New store opening", "Replenishment" |
| justification_file_upload | true | Attachments allowed |
| resubmission_enabled | true | Rejected orders can be revised and resubmitted |
| delegation_enabled | true | Approvers can delegate |
| auto_rejection_enabled | TBD | Auto-reject after timeout? |
Print on Demand ON
ELC has customizable products where field reps customize using templates and proof before ordering. PrintXpand is the confirmed integration (contract signed February 2026).
The signed contract confirms B2B template governance (per-customer and per-customer-group assignment), brand compliance validation (node-level locking, DPI validation, prevention of unauthorized modifications), SVG-to-PDF rendering up to 240x22" at 300 DPI, and S3 delivery of production files. These capabilities are in scope.
| Setting | ELC value | Notes |
|---|---|---|
| enable_product_designer | Per product | Toggle on customizable products in PrintXpand admin |
| template_library_enabled | true | Pre-designed templates available |
| brand_color_palette | TBD | Per brand (MAC, Clinique, etc.) |
| font_library | TBD | Per brand |
| show_fold_lines | true | Fold line overlays on templates |
| show_bleed_zone | true | Bleed area highlighting |
| show_safe_zone | true | Safe zone highlighting |
| proofing_required | true | Must proof before ordering |
| max_proofing_rounds | 2 | Two proof iterations |
| allow_artwork_reuse | true | Reuse previously approved designs |
Briefing TBD
May be needed for bespoke product requests that go beyond template customization. Needs team input.
Demand Capture TBD
May be needed if ELC has buying windows or seasonal availability. Needs team input.
6. Platform module phasing
Platform modules depend on client IT availability. Phased so the storefront can go live without waiting for every integration.
Phase 1: Go live (Day 60)
The storefront goes live with the Shell, all base modules, and the three optional modules. Platform integrations at launch:
| Module | Status at launch | Notes |
|---|---|---|
| DAM Integration | Active | Products need images. Must be live. |
| CAP Sync | Active | Rate card data drives pricing. Must be live. |
| SSO / Identity | Active | Login, region assignment, approval routing. Must be live. |
| Punch Out | Deferred | ELC IT provides integration docs on their timeline. |
Phase 2: Bespoke (Day 90+)
| Module | Status | Notes |
|---|---|---|
| Print on Demand | Active | PrintXpand integration live. Templates created. Proofing operational. |
| Punch Out | TBD | May be live depending on ELC IT timeline |
Phase 3: Extensions (post-launch)
| Module | Status | Notes |
|---|---|---|
| Punch Out | Active | When ELC IT is ready |
| Briefing | TBD | If needed, enable and configure |
| Demand Capture | TBD | If needed, enable and configure |
7. Implementation timeline
First ELC region (Global/NA/APAC). Two milestones: Day 60 (fixed SKU live) and Day 90 (bespoke with Print on Demand).
Weeks 1-2: Shell + Discovery
| Activity | Owner | Dependency |
|---|---|---|
| Receive ELC brand assets | ELC | Client deliverable |
| Configure Shell with ELC branding | Tag | Brand assets |
| Guided Discovery: confirm module configs and selections | Tag + ELC | |
| Confirm approval thresholds and justification categories | ELC | Business rules |
| Initiate DAM, SSO, and CAP integrations | Tag + ELC IT | IT availability |
| Begin DI CAP rate card construction | Rate card team | ELC rate card data |
Weeks 3-6: Base configuration + platform integration
| Activity | Owner |
|---|---|
| Configure Navigation: categories, campaign collections, brand paths | Tag |
| Configure Catalog: product types, filters, labels, campaign groupings | Tag |
| Configure Pricing: 3 regions, 10-tier, tax display per region | Tag |
| Configure Ordering: checkout flow, address book, outlet validation | Tag |
| Complete DAM Integration: product imagery flowing | Tag + ELC IT |
| Complete CAP Sync: pricing data every 4 hours | Tag + rate card |
| Complete SSO/Identity: login, region assignment, HR approval mapping | Tag + ELC IT |
| Load ELC product catalog | Tag |
| Admin pre-load outlet addresses | Tag |
Weeks 7-8: Optional modules + UAT
| Activity | Owner |
|---|---|
| Configure Multi-Ship: address groups, CSV upload, batch processing | Tag |
| Configure Approval: tiers, justification, delegation, notifications | Tag |
| UAT with ELC users: all base and optional module flows | ELC + Tag |
| Adjustments based on UAT feedback | Tag |
Week 9: Go-live (Day 60: fixed SKU)
Fixed SKU storefront live. Field reps can log in via SSO, browse products by category/campaign/brand, see regional prices, place orders with Multi-Ship and Approval, and track everything. Every interaction instrumented.
Weeks 10-13: Print on Demand (Day 90: bespoke)
| Activity | Owner |
|---|---|
| PrintXpand integration completion | Tag engineering |
| Create ELC product templates in PrintXpand admin | Tag + ELC |
| Configure Print on Demand: proofing, brand palettes, fonts per brand | Tag |
| UAT: print on demand flows (customize, preview, proof, order) | ELC + Tag |
| Go-live: bespoke products with Print on Demand | Tag |
8. Subsequent ELC markets
After the first three regions launch, each new ELC market follows a compressed path. The modules are already built. The process is already refined.
| Phase | Activities | Estimated duration |
|---|---|---|
| Shell + Discovery | New Shell config (branding, currency, language). Guided module selection: likely same optional modules, confirm per market. | 1 week |
| Market data | Rate card for this market. Product catalog subset. Outlet addresses. DAM imagery for market-specific products. | 2-3 weeks (client data dependent) |
| Module configuration | Pricing regions and tax rules for this market. Category structure adjustments if needed. Approval thresholds if market-specific. | 1 week |
| Platform connections | SSO for this market's users. DAM and CAP sync configured for market scope. | 1-2 weeks (ELC IT dependent) |
| UAT + Go-live | Testing validates configuration, not custom code. Standardized training materials with market screenshots. | 1-2 weeks |
For subsequent ELC markets, the bottleneck shifts from Tag development effort to ELC data readiness: rate card data, product catalog, outlet addresses, brand assets for that market, SSO configuration from ELC IT. Tag's configuration work compresses to days. The timeline is driven by how fast ELC can provide market-specific data.
9. What this proves
This spec is the first test of the modular architecture. What it demonstrates:
Every config value references a defined module field. Nothing is ad hoc. The Navigation module's config surface says browse_by_campaign_collection is a boolean. ELC's value is true.
The optional modules are composable. Multi-Ship replaces the checkout flow. Approval injects business justification. Print on Demand attaches design data. They don't conflict because the integration patterns (replace, inject, attach) are defined.
The timeline is module-driven. Day 60 maps to "Shell + base + Multi-Ship + Approval, with DAM/CAP/SSO live." Day 90 adds Print on Demand. Each milestone is defined by which modules are live.
Multi-market scaling is built in. The first three regions are the investment. Each subsequent ELC market reuses the modules and follows a compressed path. The effort curve bends down with every deployment.
TBD items are explicit. Every TBD has a named dependency. Nothing is vaguely open.
Platform modules are phased independently. The storefront can go live without Punch Out. Platform modules operate on the client IT's timeline, not ours.
The compounding starts within ELC. The first non-ELC client benefits from everything the ELC program built and refined. By that point, the modules work, the process is proven, and the timeline is a formula.
10. Open questions
| Category | Question | Status |
|---|---|---|
| ELC | Approval tier thresholds: what dollar amounts trigger each tier? | Needed |
| ELC | Predefined justification categories | Needed |
| ELC | Auto-rejection policy: should orders auto-reject after timeout? | Needed |
| ELC | Item-level approval: needed, or is order-level sufficient? | Needed |
| ELC | Analytics provider preference: GA4 or Adobe Analytics? | Needed |
| ELC | Tax display rules per region: inclusive vs exclusive? | Needed |
| ELC | Brand assets (logo, colors, fonts, guidelines) | Needed |
| ELC | Which products will be customizable (Print on Demand)? | Needed |
| ELC | Outlet validation rules for address book? | Needed |
| ELC | Does ELC need Briefing? Demand Capture? | Discovery |
| ELC | Currency display per region: market defaults or specific preference? | Needed |
| ELC | How many subsequent markets are in the pipeline? Which are prioritized? | Discovery |
| Engineering | PrintXpand integration status: what's built, what's remaining? | Needed |
| Engineering | Magento 2.4.8-p3 compatibility with PrintXpand: verified? | Needed |
| Engineering | How does PrintXpand design data attach to cart items? | Needed |
| Engineering | Does ELC need 3D preview for any product types? | Needed |
| Engineering | Do brand color palettes and font libraries differ per ELC brand within Print on Demand? | Needed |
| Product | Briefing module requirements: what should the workflow cover? | Needed |
| Product | Demand Capture requirements: buying window mechanics? | Needed |
1. Client overview
Content for Reyes client overview is in progress.
2. The trajectory
Content for Reyes trajectory is in progress.
3. Shell configuration
Content for Reyes Shell configuration is in progress.
4. Base module configurations
Content for Reyes base module configurations is in progress.
5. Optional module selections
Content for Reyes optional module selections is in progress.
6. Platform module phasing
Content for Reyes platform module phasing is in progress.
7. Implementation timeline
Content for Reyes implementation timeline is in progress.
8. Subsequent markets
Content for Reyes subsequent markets is in progress.
9. What this proves
Content for what the Reyes implementation proves is in progress.
10. Open questions
Content for Reyes open questions is in progress.