Skip to content

docs: BFF cart and PDP override guide — connector-override approach (CXSPA-13000) - #21827

Open
npapp-dev002 wants to merge 56 commits into
developfrom
docs/CXSPA-13000
Open

docs: BFF cart and PDP override guide — connector-override approach (CXSPA-13000)#21827
npapp-dev002 wants to merge 56 commits into
developfrom
docs/CXSPA-13000

Conversation

@npapp-dev002

@npapp-dev002 npapp-dev002 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds docs/spa-bff-integration-guide.md, a guide explaining how to
replace direct OCC calls in a standard Spartacus Classic storefront with BFF
procedures. The storefront UI, components, and Angular routing are unchanged —
only the data layer is replaced.

Why a BFF simplifies the UI layer

With direct OCC the browser is responsible for fetching OAuth2 tokens, the OCC
base URL is embedded in index.html, and every page may make multiple
independent round trips to OCC. A BFF moves all of this server-side. The
browser talks to a single relative /bff/api endpoint using tRPC, sends no
credentials for anonymous sessions, and sees no OCC URLs.

Two integration approaches

Approach 1 — Connector override

BffCartBaseModule replaces CartConnector and CartEntryConnector inside
the lazy cart feature injector. BffProductModule replaces the three product
connectors at root level. The existing NgRx graph, facades, and UI components
are completely unchanged.

Activating: point CART_BASE_FEATURE at BffCartBaseModule in
cart-base-feature.module.ts.

Approach 2 — Facade override

BffActiveCartService implements ActiveCartFacade directly using Angular
Signals. There are no NgRx actions, reducers, or effects for cart — state is a
Signal updated in place after each BFF mutation. This is the default active
configuration in this workspace.

Activating: import BffActiveCartModule in app.module.ts and keep
cart-base-feature.module.ts pointing at the standard CartBaseModule.

PDP aggregation

The BFF exposes a product.getPageData procedure that fans three OCC calls
out in parallel server-side using Promise.allSettled, returning a merged
{ product, references, reviews } payload in one server round trip. The
document explains why the browser still makes three /bff/api calls in
Approach 1 (three independent NgRx effects, no shared connector call path)
and what would be required to reduce it to one.

Angular DI problem — documented

CartBaseCoreModule re-provides CartConnector in its lazy injector, shadowing
any root-level override. The document explains three approaches that fail and
the working solution: define connector subclasses inline in the same file as
the lazy wrapper module so the bundler cannot split them into separate chunks.

Known pitfalls documented

  • toObservable() injection context — must be called as field initializers
  • Anonymous cart guid vs code — OCC anonymous carts use guid; using
    code alone causes write operations to silently exit
  • "Added to Cart" dialog empty — AddedToCartDialogComponent waits for
    CartAddEntrySuccessEvent which is normally fired by NgRx effects; must be
    dispatched manually in the facade override
  • Dialog flicker — event must be dispatched only after _reload() completes
    so isStable() is already true and getLastEntry() finds the new entry

Test plan

  • Navigate to a product detail page; verify Network tab shows three
    /bff/api/product.* calls and no direct OCC calls
  • Add an in-stock product (429430 or 23355) to cart; verify
    cart.create and cart.addEntry appear under /bff/api/ with no direct
    OCC cart calls
  • Verify "Added to Cart" dialog shows the product name and quantity without
    flickering or spinner flash
  • Verify mini-cart badge updates after add-to-cart
  • Open DevTools → Application → Local Storage; verify no OCC token is
    stored for anonymous sessions
  • Clear localStorage, reload; verify cart recovers automatically

npapp-dev002 and others added 30 commits July 1, 2026 11:07
…with npm registry access details and component examples
Co-authored-by: Krzysztof Platis <platonn.git@gmail.com>
… state requirements and configuration examples
Co-authored-by: Paweł Fraś <fras.pawel@yahoo.com>
Co-authored-by: Paweł Fraś <fras.pawel@yahoo.com>
npapp-dev002 and others added 26 commits July 16, 2026 19:13
…fy usage in spa-bff-reference-implementation
… settings in spa-bff-reference-implementation
Co-authored-by: Paweł Fraś <fras.pawel@yahoo.com>
Documents the connector-override approach for integrating a Vivaldi BFF
with a standard Spartacus Classic storefront, including the PDP aggregation
demonstration that shows the core BFF performance benefit.

@pawelfras pawelfras left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to confirm who's the target of this documentation. If I'm not mistaken, we're targeting current/future users of classic Spartacus. If that's true, we could omit all Spartacus-BFF references, because, at this stage, this is a separate product with a separate target - I wouldn't mix-and-match these two and recommend doing that in customer's apps in documentation for classic Spartacus.

- A BFF can be introduced into a running production storefront

**What it does not give you:**
- Fully clean architecture — unused OCC code remains in the browser bundle

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query: The statement seem to be right due to how we provide the code and how barrel files works, but would be good double-checking if maybe tree-shaking does the work if particular occ-related layer is completely unused in the code.


---

### Approach B — Purpose-built BFF storefront (spartacus-bff)

@pawelfras pawelfras Aug 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

major: I don't feel comfortable with proposing this option for several reasons:

  • Spartacus-BFF libraries are not as mature as classic Spartacus
  • Spartacus-BFF contracts are MCS-based and may strongly differ from what is expected by classic Spartacus UI
  • not all features from classic Spartacus are implemented in Spartacus-BFF
  • from the architectural point of view, it might not be optimal to propose customers depending on two different products (with different release cycles), yet with similar public API - this will decrease the DX and this is what we want to avoid now in Spa-BFF by cutting off the dependency to classic Spa libraries.

Being honest, I'm not sure if we should mention spartacus-bff project/libraries in this document. They are two separate products and spartacus-bff was not ment to be integrated with classic Spartacus. We could base on how BFF is used in spa-bff, but for classic Spa customers, it should be rather from-scratch description, not a usage of spa-bff libraries.

EDIT: apoloigies, Only now I see it is not about combining both, classic Spartacus and Spartacus-BFF in one library. Still, I'm not sure if we should mention the product in document for classic Spartacus users. But I might be wrong.

Comment on lines +123 to +125
**Approach B** is the target architecture — what a new storefront would be
built on, or what an existing storefront would move to over time by replacing
feature modules one by one with their `@spartacus-bff/*` equivalents.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

major: I would be careful with this statement since it is not something sure at this state and it may give classic Spartacus customers rise to the unfounded fear that they will have to switch to a new product in the future.


---

## Which approach should I choose?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

major: I'm not sure if we should include this or similar section, since this sounds like we recommend using BFF this way of another for classc Spartacus customers. I'm not sure if that's true at this moment and if we should recommend anything. I might be mistaken, but I'd stick to real-life examples of how to use BFF in classic Spa, without any recommendation.

Base automatically changed from doc/CXSPA-13587 to develop August 6, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants