Urban Store’s shopping cart is built on a dual-persistence architecture: a Zustand store backed byDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ALEJ4NDRO2025/urban-store/llms.txt
Use this file to discover all available pages before exploring further.
localStorage provides instant, lag-free UI updates with zero network round-trips, while a MongoDB backend cart document keeps the cart synchronized across devices and browser sessions. Every mutation — adding, updating, or removing items — is committed to localStorage immediately and then flushed asynchronously to the backend via a full-cart sync operation.
Dual Persistence Architecture
localStorage. After login, loadCartFromBackend() is called — if the backend cart contains items, those items overwrite the local copy, reconciling any drift from a different device.
Zustand Store API
The cart store is exported asuseCartStore from app/lib/cartStore.js. All mutating methods are async and call syncWithBackend() as a fire-and-forget side effect after updating local state.
addItem(newItem)
Adds a product to the cart. If an identical variant (same slug + size + color) already exists, its quantity is incremented. Updates
localStorage and triggers a backend sync.updateItemQuantity(slug, size, color, qty)
Sets the quantity of a specific variant to
qty. Updates localStorage and syncs to backend.removeItem(slug, size, color)
Removes all units of a specific variant. Updates
localStorage and syncs to backend.clearCart()
Empties the cart completely — sets
items to [], clears localStorage, and syncs an empty cart to the backend.loadCartFromBackend()
Fetches the cart document from
GET /api/cart/ and replaces local state if the backend cart is non-empty. Called on login.syncWithBackend(items)
Posts the full current items array to
POST /api/cart/sync/, replacing the backend cart atomically. Called internally after every mutation.createOrder(shippingAddress, notes, items)
Builds an order payload and posts to
POST /api/orders/. On success, clears the cart locally and syncs the empty state to the backend.Adding an Item — Code Example
addItem will throw Error('No autenticado') if no access token is found in localStorage. Always ensure the user is logged in before calling cart mutations.Cart Item Structure
Each item in theitems array conforms to the CartItem embedded document schema defined in cart/models.py:
price_at_time field captures the product price at the moment the item was added to the cart, so price changes after the item was added do not affect the cart total.
Backend Sync — POST /api/cart/sync/
The sync endpoint replaces the entire cart document for the authenticated user with whatever items are sent in the request body. This is a full replace, not a merge.
total and item_count via cart.calculate_totals() before saving.
Authentication Requirement
All cart endpoints (GET /api/cart/, POST /api/cart/sync/, etc.) require a valid JWT Bearer token. The backend extracts the user identity from the email field in the JWT payload. Requests without a valid Authorization: Bearer <token> header receive a 401 Unauthorized response.
Cart Total Calculation
The cart total is computed client-side in the Zustand store’stotal getter:
price_at_time × quantity summed across all items. null or unparseable prices are treated as 0.
Checkout Flow
Review Cart
The customer reviews cart contents and the computed total in the cart sidebar or cart page.
Fill Shipping Form
The customer enters their shipping address: email, name, phone, street address, city, department, and country.
Create Order
createOrder(shippingAddress, notes, items) is called. The cart items are posted to POST /api/orders/ along with the shipping address. The backend decrements stock and returns an order object with status pending.Stripe Payment
The frontend calls
POST /api/payments/create-payment-intent/ with the new order_id to receive a client_secret, then uses @stripe/react-stripe-js to render the PaymentElement and collect card details.