
Cart Logic
- 105 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Build a robust shopping cart with add/remove/update operations, cross-device session persistence, and guest-to-account cart merge on login.
About
A skill for implementing shopping cart behavior: line-item operations, persistence across devices, and merging a guest cart into an account at login. A developer uses it to configure platform carts or build cart logic for a headless storefront.
- Add/remove/update, persistence, and cart merge patterns
- Configure built-in carts; custom code only for headless
Cart Logic by the numbers
- 105 all-time installs (skills.sh)
- Ranked #2,973 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill cart-logicAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 105 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Build a robust shopping cart with add/remove/update operations, cross-device session persistence, and guest-to-account cart merge on login.
Files
Cart Logic
Overview
Cart logic covers how your store manages items a shopper intends to buy: adding, removing, and updating items; persisting the cart across page loads and devices; and merging a guest cart into an account when the customer logs in. On Shopify, WooCommerce, and BigCommerce, the cart is built into the platform — the goal is to configure it correctly and extend it when needed. Custom code is only required for headless storefronts.
When to Use This Skill
- When cart state is lost when users navigate between pages (missing persistence)
- When guest cart items disappear after login (missing merge logic)
- When implementing real-time cart price updates (coupons, quantity changes, shipping estimates)
- When building a headless storefront that needs a custom cart implementation
Core Instructions
Step 1: Understand how your platform handles cart logic
| Platform | Cart Behavior | Where to Configure |
|---|---|---|
| Shopify | Built-in cart with automatic persistence; uses cookies/localStorage | Theme Liquid templates + Cart API; extend with Cart Transform Shopify Function |
| WooCommerce | Built-in cart with session persistence; configures via PHP hooks | WooCommerce settings + woocommerce_add_cart_item_data and woocommerce_cart_item_price filters |
| BigCommerce | Built-in Storefront Cart API; cart persists via cookie | BigCommerce Stencil theme + Storefront Cart API |
| Custom / Headless | Must build from scratch using platform APIs or Shopify/BigCommerce Storefront API | See Custom / Headless section below |
Step 2: Configure and extend cart behavior
---
Shopify
Shopify's cart is managed automatically. To extend it:
Customize the cart drawer or page: 1. Go to Online Store → Themes → Customize 2. Select the cart section and configure: cart type (drawer vs. page), item display, quantity controls 3. Enable Cart notes and Shipping estimate in the cart settings if needed
Enable cart persistence across devices (requires accounts):
- Shopify automatically persists cart for logged-in customers; the cart is stored server-side on their account
- For guest carts, Shopify uses a
cart_tokencookie (30-day expiry by default)
Merge guest cart on login:
- Shopify handles this automatically — when a guest logs in, their cart is merged with any existing account cart
Cart customization via Shopify Functions: Use Cart Transform Shopify Functions to modify cart items, apply custom discounts, or bundle products. Go to Settings → Custom data and deploy a Cart Transform function via the Shopify CLI.
Custom cart upsells and cross-sells: Install CartHook, ReConvert, or Frequently Bought Together from the Shopify App Store for cart upsell logic without custom code.
---
WooCommerce
WooCommerce's cart is built-in and session-based.
Configure cart behavior: 1. Go to WooCommerce → Settings → Products → General to configure cart and add-to-cart behavior 2. Enable or disable Redirect to cart page after successful addition based on your store's UX preference 3. Under WooCommerce → Settings → Advanced → Cart page, verify the cart page is assigned
Enable persistent cart for logged-in users: 1. Go to WooCommerce → Settings → Accounts & Privacy 2. Enable Persistent cart — this stores a logged-in customer's cart in the database so it survives across sessions and devices
Guest cart to account merge: WooCommerce automatically merges the guest cart with the customer's saved cart when they log in. To ensure this works, keep Persistent cart enabled.
Extend cart item data (e.g., for product customization options): Use the woocommerce_add_cart_item_data filter in your theme's functions.php or a custom plugin to attach extra data to cart items (gift messages, engraving text, etc.).
Cart abandonment tracking: Install CartFlows or WooCommerce Cart Abandonment Recovery plugin to track and recover abandoned carts.
---
BigCommerce
BigCommerce uses its Storefront Cart API for cart management.
Configure cart settings: 1. Go to Settings → Storefront to configure cart and checkout behavior 2. Cart persistence is automatic via BigCommerce's session management
Customize the cart via Stencil theme: Edit cart templates in your Stencil theme (templates/components/cart/) to modify the cart page layout, item display, and available actions.
Cart upsells: Use the BigCommerce Cart API to detect items in the cart and conditionally show related products or promotions in the cart template.
---
Custom / Headless
For a headless storefront, use your platform's Storefront API rather than building cart storage from scratch:
Shopify Storefront API (recommended for Shopify-backed headless stores):
// Create a cart
const createCart = async () => {
const response = await fetch(`https://${SHOP_DOMAIN}/api/2024-01/graphql.json`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': STOREFRONT_TOKEN,
},
body: JSON.stringify({
query: `
mutation cartCreate($input: CartInput!) {
cartCreate(input: $input) {
cart { id checkoutUrl }
userErrors { field message }
}
}
`,
variables: { input: { lines: [{ merchandiseId: variantGid, quantity: 1 }] } },
}),
});
const { data } = await response.json();
return data.cartCreate.cart;
};
// Add an item to an existing cart
const addToCart = async (cartId, variantGid, quantity) => {
const response = await fetch(`https://${SHOP_DOMAIN}/api/2024-01/graphql.json`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': STOREFRONT_TOKEN,
},
body: JSON.stringify({
query: `
mutation cartLinesAdd($cartId: ID!, $lines: [CartLineInput!]!) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart { id totalQuantity cost { totalAmount { amount currencyCode } } }
}
}
`,
variables: { cartId, lines: [{ merchandiseId: variantGid, quantity }] },
}),
});
const { data } = await response.json();
return data.cartLinesAdd.cart;
};Store the cartId in a cookie or localStorage. On login, use cartBuyerIdentityUpdate to associate the cart with the customer's account — Shopify handles the merge automatically.
BigCommerce Storefront API (for BigCommerce-backed headless stores):
Use the BigCommerce Storefront Cart API (/api/storefront/carts) which handles cart creation, item management, and customer association automatically.
Step 3: Implement key cart UX behaviors
Regardless of platform, these are the cart behaviors that most affect conversion:
1. Show mini-cart on add-to-cart — most Shopify, WooCommerce, and BigCommerce themes support a slide-out cart drawer that opens when an item is added; enable this instead of redirecting to the cart page 2. Show stock levels in the cart — display "Only 2 left" warnings on items with low inventory; both Shopify and WooCommerce support this via metafields and cart item data 3. Guest cart persistence — ensure guest carts survive for at least 30 days so returning visitors find their items; Shopify does this by default; WooCommerce requires the session duration setting to be configured 4. Free shipping progress bar — show a "You're $X away from free shipping" bar in the cart; install Free Shipping Bar (Shopify) or WooCommerce Free Shipping Bar plugin
Best Practices
- Use your platform's native cart — Shopify, WooCommerce, and BigCommerce carts are battle-tested and handle edge cases (stock validation, price changes, tax calculation) correctly
- Enable persistent cart for logged-in customers — all three platforms support server-side cart storage for accounts; enable it
- Validate stock at checkout, not only on add-to-cart — items may sell out while in a guest's cart; re-validate at checkout time (platforms do this automatically)
- Show the cart total prominently — including item count and subtotal; reduces anxiety about total spend
- For headless: use the platform's Storefront API — Shopify and BigCommerce Storefront APIs are production-hardened and handle cart merging, stock checks, and checkout initiation correctly
Common Pitfalls
| Problem | Solution |
|---|---|
| Cart disappears when user logs in (WooCommerce) | Ensure Persistent cart is enabled in WooCommerce → Settings → Accounts & Privacy |
| Guest cart is empty after browser restart | Check cookie expiry settings; Shopify uses 30-day cart tokens by default; WooCommerce session duration is configurable |
| Same item added twice instead of incrementing quantity | The platform's native cart handles this; if using headless with Storefront API, use cartLinesUpdate to increment quantity on existing lines |
| Cart shows outdated prices after a price change | Shopify and WooCommerce automatically use current prices at checkout, not add-to-cart prices; a "price changed" notice appears automatically |
| Custom add-to-cart code bypasses stock checks | Always use the platform's official add-to-cart mechanisms; custom code that writes directly to cart storage skips inventory validation |
Related Skills
- @checkout-flow-optimization
- @guest-checkout
- @inventory-tracking
- @stripe-integration
{
"context": "Tests whether the agent correctly defines the cart data model with all required fields, implements upsert semantics on add-to-cart, captures price at time of add, delegates quantity≤0 updates to remove, and always recalculates totals server-side.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Cart status field",
"max_score": 6,
"description": "Cart schema / data model includes a 'status' field with values that include 'active', 'abandoned', and 'converted'"
},
{
"name": "Guest token field",
"max_score": 6,
"description": "Cart schema includes a guest_token field (UUID-based) for identifying guest carts, and user_id is null for guests"
},
{
"name": "unit_price vs original_unit_price",
"max_score": 8,
"description": "Line item schema includes both a unit_price (price at time of add) and an original_unit_price (before discounts) field"
},
{
"name": "Price captured at add time",
"max_score": 10,
"description": "addToCart captures the variant's price as unit_price at the time the item is added, not fetched dynamically on cart reads"
},
{
"name": "Upsert on duplicate variant",
"max_score": 12,
"description": "addToCart checks whether the variant already exists in the cart and increments quantity rather than creating a duplicate line item"
},
{
"name": "Delegate remove on qty ≤ 0",
"max_score": 8,
"description": "updateCartItem delegates to the remove function when the requested quantity is 0 or less, rather than setting quantity to 0"
},
{
"name": "recalculateCart after mutation",
"max_score": 10,
"description": "recalculateCart (or equivalent) is called after every cart mutation: add, update, and remove"
},
{
"name": "Server-side subtotal",
"max_score": 10,
"description": "subtotal is computed server-side as sum(unitPrice * quantity); totals are not accepted from the client"
},
{
"name": "Discount applied server-side",
"max_score": 8,
"description": "Discount / coupon is applied server-side during recalculation; total = max(0, subtotal - discount)"
},
{
"name": "Totals rounded to 2 decimals",
"max_score": 8,
"description": "subtotal, discountAmount, and total are rounded / fixed to 2 decimal places during recalculation"
},
{
"name": "Stock validation on add",
"max_score": 14,
"description": "addToCart validates that the variant exists (404 if not found) and checks available stock before adding (409 if insufficient and backorders not allowed)"
}
]
}
Build Cart API for an Online Apparel Store
Problem/Feature Description
A small apparel startup called ThreadShop is building its e-commerce platform and needs a shopping cart backend. The engineering team has a basic product catalog in place (products with variants for size and color), but has no cart system yet. The product manager has flagged two recurring complaints from their beta testers: (1) adding the same product twice results in two separate line items instead of combining them, and (2) the total shown in the cart doesn't always match what customers are actually charged at checkout because the front-end was sending its own calculated totals.
The team needs a clean implementation of the core cart API in a single JavaScript/Node.js module. The implementation should cover adding items to the cart, updating quantities, removing items, and computing accurate cart totals — all without relying on the client to submit the final price.
Output Specification
Produce a single file cart-api.js that contains:
- A
getOrCreateCart(userId, guestToken)helper that returns a cart ID (you may use an in-memory store or stub the DB calls) addToCart(cartId, variantId, quantity, variantData)— adds or updates a line itemupdateCartItem(cartId, itemId, quantity)— updates quantity; delegates to remove when quantity ≤ 0removeCartItem(cartId, itemId)— removes a line itemrecalculateCart(cartId)— recomputes subtotal, discount, and total- A brief
CART_SCHEMA.mdfile documenting the data model your implementation assumes (fields on the cart and on each line item)
You may use stubs/mocks for the database layer. Focus on the logic and data structure rather than actual DB connectivity.
{
"context": "Tests whether the agent correctly persists the guest cart token in an httpOnly cookie (not localStorage), uses correct cookie settings, implements optimistic UI for add-to-cart with proper revert-on-failure, and uses the React useReducer/context pattern for cart state.",
"type": "weighted_checklist",
"checklist": [
{
"name": "httpOnly cookie (not localStorage)",
"max_score": 12,
"description": "Guest cart token is stored using an httpOnly cookie, NOT in localStorage or sessionStorage"
},
{
"name": "Cookie named cart_token",
"max_score": 6,
"description": "The guest cart cookie is named 'cart_token'"
},
{
"name": "Cookie secure flag",
"max_score": 8,
"description": "Cookie is set with secure: true (or secure: process.env.NODE_ENV === 'production') to ensure HTTPS-only in production"
},
{
"name": "Cookie sameSite lax",
"max_score": 6,
"description": "Cookie is set with sameSite: 'lax'"
},
{
"name": "Cookie maxAge 30 days",
"max_score": 6,
"description": "Cookie maxAge is set to 30 days (2592000000 ms or 30 * 24 * 60 * 60 * 1000)"
},
{
"name": "UUID guest token",
"max_score": 6,
"description": "Guest token is generated as a UUID (using uuid library, crypto.randomUUID, or similar)"
},
{
"name": "Optimistic add dispatch",
"max_score": 12,
"description": "addItem dispatches an optimistic state update to the cart BEFORE awaiting the API response"
},
{
"name": "Revert on API failure",
"max_score": 10,
"description": "On API call failure in addItem, the cart state is reverted by re-fetching the current cart from the server"
},
{
"name": "useReducer for cart state",
"max_score": 8,
"description": "Cart state is managed with useReducer (not useState) with a cartReducer function"
},
{
"name": "CartContext and useCart hook",
"max_score": 8,
"description": "A CartContext is created and a useCart hook exported that calls useContext(CartContext)"
},
{
"name": "DESIGN_NOTES mentions httpOnly rationale",
"max_score": 8,
"description": "DESIGN_NOTES.md mentions that httpOnly cookie was chosen over localStorage for security (XSS protection)"
},
{
"name": "DESIGN_NOTES mentions optimistic UI",
"max_score": 10,
"description": "DESIGN_NOTES.md mentions the optimistic update strategy (update immediately, revert on failure)"
}
]
}
Shopping Cart Frontend with Guest Session Support
Problem/Feature Description
Bloom & Co, a boutique flower delivery service, is launching a React-based storefront. They want customers to be able to browse and add flowers to their cart without needing to create an account — and importantly, their cart should persist if they close the tab and return an hour later. The team is worried about security after reading about XSS attacks that steal session data, so they want the cart session to be as safe as possible.
On the frontend, the UX team has pushed back hard on any "loading spinner" shown every time a customer clicks "Add to Basket" — they want the cart icon to update instantly when the button is clicked, even if the API call hasn't completed yet. The team needs both a server-side session helper (Node.js) and a React cart context wired up together.
Output Specification
Produce the following files:
lib/cartSession.js— Node.js helper that creates or retrieves a cart for both authenticated and guest userscontext/CartContext.jsx— React context, provider, anduseCarthook with cart state and anaddItemfunction- A brief
DESIGN_NOTES.mdexplaining the session token storage decision and the UI update strategy used
You may stub out the database layer and API calls. Focus on the session management logic and the React state management pattern.
{
"context": "Tests whether the agent correctly implements the guest-to-user cart merge: reassigning when no user cart exists, using Math.max for quantity conflicts, marking the guest cart as 'abandoned' (not deleted), calling recalculateCart after merge, and handling empty guest carts as a no-op.",
"type": "weighted_checklist",
"checklist": [
{
"name": "No-op on empty guest cart",
"max_score": 8,
"description": "mergeGuestCartOnLogin returns early (no-op) when the guest cart does not exist or has no items"
},
{
"name": "Reassign when no user cart",
"max_score": 12,
"description": "When the user has no existing active cart, the guest cart is reassigned to the user (userId set, guestToken cleared) rather than creating a new cart"
},
{
"name": "Max quantity on conflict",
"max_score": 14,
"description": "When the same variant exists in both guest and user carts, the merged quantity is Math.max(guestQty, userQty) — the higher of the two"
},
{
"name": "Does NOT sum quantities",
"max_score": 8,
"description": "The merge does NOT add guest and user quantities together (i.e., does not use guestQty + userQty for conflicting variants)"
},
{
"name": "Non-overlapping items added",
"max_score": 10,
"description": "Guest items that do not exist in the user cart are added (created) in the user cart, not discarded"
},
{
"name": "Guest cart marked abandoned",
"max_score": 12,
"description": "After merge, the guest cart status is updated to 'abandoned', not deleted from the database"
},
{
"name": "Guest cart NOT deleted",
"max_score": 8,
"description": "The implementation does NOT call a delete/destroy operation on the guest cart — it only updates its status"
},
{
"name": "recalculateCart called after merge",
"max_score": 10,
"description": "recalculateCart (or equivalent total recalculation) is called on the user cart after the merge completes"
},
{
"name": "Test: no-user-cart case",
"max_score": 9,
"description": "Test file includes a test case for when the user has no existing active cart (guest cart reassignment path)"
},
{
"name": "Test: overlapping variants",
"max_score": 9,
"description": "Test file includes a test case where the same variant exists in both carts and verifies max-quantity logic"
}
]
}
Cart Continuity Across Guest and Authenticated Sessions
Problem/Feature Description
NestMarket, an online home-goods retailer, is losing sales because customers who browse and fill their cart as a guest find it empty after signing in or creating an account. The support team gets daily complaints: "I added 4 items before logging in and they all disappeared!" The development team needs to fix this by implementing a proper cart handoff when a guest authenticates.
There's a wrinkle though: a returning customer may have leftover items in their account cart from a previous session. When that customer's fresh guest cart is merged in, the team wants a sensible conflict resolution strategy — if the same product appears in both carts, the system should keep whichever quantity reflects the customer's most recent intent. After merging, the old guest cart should remain in the database for audit purposes but should no longer be shown as active.
Write a standalone Node.js module implementing this merge logic. Stub out any database calls so the code can be read and reviewed without a running database.
Output Specification
Produce:
lib/mergeCart.js— the cart merge functionlib/mergeCart.test.js— unit tests (using any test framework, or plain assertions) covering: guest cart with no matching user cart, guest cart with overlapping variants, guest cart with non-overlapping variants, and an empty guest cart (no-op)
Keep the test file runnable with node lib/mergeCart.test.js or a standard test runner.
{
"name": "finsi/cart-logic",
"version": "0.1.0",
"summary": "Shopping cart state management — add/remove/update, persistence, merge strategies",
"skills": {
"cart-logic": {
"path": "SKILL.md"
}
}
}