Skip to content

feat(apps-vtex): Cart v2 — modular, granular, framework-agnostic cart#374

Open
JonasJesus42 wants to merge 1 commit into
mainfrom
vtex-cart-fragmentation
Open

feat(apps-vtex): Cart v2 — modular, granular, framework-agnostic cart#374
JonasJesus42 wants to merge 1 commit into
mainfrom
vtex-cart-fragmentation

Conversation

@JonasJesus42

@JonasJesus42 JonasJesus42 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduces a two-dimension cart fragmentation system for @decocms/apps-vtex: sections (controls what VTEX computes via expectedOrderFormSections) and projection (none / summary / summary+items / minicart / raw, controls what the server sends to the browser). The result: no OrderForm created until the first add-to-cart, add-to-cart sends 3 sections instead of 15, and the browser receives ~1 KB instead of ~40 KB by default. Optimistic badge bump + server reconciliation live in the hook — the storefront never reimplements them. The agnostic contract lives in @decocms/apps-commerce (Shopify/Wake can reuse the same types). Includes a TanStack Query adapter (6 hooks, useShipping keyed by {postalCode,items} for client-side cache), 281 passing tests, and a skill with usage guide, projection decision table, and gradual v1→v2 migration guide.

New surface

  • @decocms/apps-commerce/types/cartCartSection, CartProjection, CartSummary, CartItemSlim, SECTIONS_MINIMAL/DRAWER/FULL
  • vtex/loaders/cart/{summary,full,shipping,gifts,attachments} — granular read-path loaders, each requesting only the sections it needs
  • createCart({ invoke }) — factory: useCart, useCartSummary, useAddToCart, useShipping, useGifts, useAttachments, resetCart; add() returns the projected payload for toasts without a second fetch
  • createCartQuery({ invoke }) — optional TanStack Query adapter with full parity
  • actions/checkout.ts: addItemsToCartV2, updateCartItemsV2, addCouponToCartV2, getOrCreateCartV2
  • .agents/skills/vtex-cart-v2/SKILL.md — full usage, projection decision guide, gradual migration guide

Test plan

  • vitest run packages/apps-vtex packages/apps-commerce — 281 tests passing (26 files)
  • tsc --noEmit on apps-vtex and apps-commerce — 0 errors
  • biome check — 0 errors on all touched files
  • E2E smoke: home load with no add → 0 calls to /api/checkout/pub/orderForm; add-to-cart → body contains SECTIONS_MINIMAL, response is slim summary+items; open drawer → cart/full called with 9 sections

🤖 Generated with Claude Code


Summary by cubic

Cart v2 for @decocms/apps-vtex adds two-way cart fragmentation (sections and projection) to cut VTEX compute and shrink client payloads. No cart is created until the first add; add-to-cart requests only minimal sections and returns a slim response with optimistic badge updates.

  • New Features

    • Platform-agnostic cart types in @decocms/apps-commerce/types/cart with SECTIONS_MINIMAL, SECTIONS_DRAWER, and SECTIONS_FULL.
    • Granular loaders: vtex/loaders/cart/{summary,full,shipping,gifts,attachments}.
    • createCart({ invoke }) hooks: useCart, useCartSummary, useAddToCart, useShipping, useGifts, useAttachments, resetCart (optimistic bump + server reconciliation; add() returns the projected payload).
    • Optional TanStack Query adapter createCartQuery({ invoke }); @tanstack/react-query is an optional peer.
    • V2 checkout actions: getOrCreateCartV2, addItemsToCartV2, updateCartItemsV2, addCouponToCartV2 with server-side projectOrderForm to enforce projections.
  • Migration

    • Stop creating a cart on mount; use useCartSummary + vtex/loaders/cart/summary for the badge.
    • Load the drawer on demand via vtex/loaders/cart/full.
    • Keep v1 running while migrating; components can switch to the new hooks one by one.
    • If your app uses react-query, swap to createCartQuery; otherwise use createCart.

Written for commit aed1d8c. Summary will update on new commits.

Review in cubic

Introduces a two-dimension fragmentation system for the VTEX cart:
- `sections` (expectedOrderFormSections) — limits what VTEX computes
- `projection` (none/summary/summary+items/minicart/raw) — limits what goes to the browser

Key outcomes vs the legacy cart:
- Lazy: no OrderForm created until first add-to-cart (eliminates the eager
  mount-time VTEX call for browsing-only visitors)
- Default add-to-cart sends only SECTIONS_MINIMAL (3 sections instead of 15)
  and returns a slim `{ totalItems, total, items:[slim] }` to the browser
- Optimistic badge bump + server reconciliation built into the hook; storefront
  never re-implements this logic

New files:
- packages/apps-commerce/src/types/cart.ts — agnostic contract (CartSection,
  CartProjection, CartSummary, CartItemSlim, SECTIONS_MINIMAL/DRAWER/FULL)
- packages/apps-vtex/src/utils/cartProjection.ts — projectOrderForm()
- packages/apps-vtex/src/loaders/cart/{summary,full,shipping,gifts,attachments}
- packages/apps-vtex/src/hooks/createCart.ts — factory (useCart, useCartSummary,
  useAddToCart, useShipping, useGifts, useAttachments, resetCart)
- packages/apps-vtex/src/hooks/cartQuery.ts — optional TanStack Query adapter
  with 6 hooks (useShipping keyed by {postalCode,items} for client-side cache)
- .agents/skills/vtex-cart-v2/SKILL.md — full usage, projection decision guide,
  gradual migration guide

Modified:
- actions/checkout.ts: addItemsToCartV2/updateCartItemsV2/addCouponToCartV2/
  getOrCreateCartV2 + unified DEFAULT_EXPECTED_SECTIONS from SECTIONS_FULL
- invoke.ts: v2 action entries for generate-invoke TanStack createServerFn
- manifest.gen.ts: 5 new vtex/loaders/cart/* entries
- apps-vtex package.json: @tanstack/react-query as optional peerDep

add() returns the projected payload so callers can drive a toast without a
second fetch; updateQuantity/removeItem/addCoupon return the projected Minicart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@JonasJesus42
JonasJesus42 requested a review from a team July 16, 2026 00:54
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.

1 participant