AstroBaaS

Checkout & payments

Shopping Cart

Free — GPL coresize Lplanned, not built

Generated from docs/plan/core/shopping-cart/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Customers need to hold products before purchase. A shopping cart is a fundamental e-commerce feature that holds items, allows quantity adjustment, and persists across sessions.

The problem

Without a shopping cart, customers either add items directly to a purchase (no browsing first) or manually remember what they wanted. A cart lets shoppers collect items, review totals, and adjust quantities before checkout.

What it does

  • Cart stored in browser session storage (or localStorage for persistence); synced with server at checkout
  • Add items: { product_id, variant_id (optional), qty } → add to cart or increment existing line
  • Remove items: delete a line from cart
  • Update quantity: change qty on a line; if qty becomes 0, remove the line
  • View cart: display all lines with product name, variant, qty, unit price, line total
  • Coupon application: append coupon code to cart; API validates and applies discount
  • Shipping method selection: user chooses from available methods; cart recalculates total with shipping
  • Totals calculation: display subtotal, discount, shipping, tax, total (read-only; recomputed server-side at checkout)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Cart merge on login — if a guest adds items, then logs in, do we merge the guest cart with their saved cart? This is a UX design choice left to the storefront theme.
  • Saved carts or wishlists — separate features from the active cart.
  • Abandoned cart recovery — that’s marketing, not the cart itself. (There is a separate paid ‘cart-abandonment-recovery’ module.)

Data model

Cart is client-side only (stored in localStorage or sessionStorage). On the server side, no Cart collection — checkout validates items against live product data at POST /api/orders. Transient state: no persistence.

API

  • POST /api/cart/add — add item, return updated cart
  • POST /api/cart/remove — remove item by product_id + variant_id
  • POST /api/cart/update — update qty by product_id + variant_id
  • GET /api/cart — return current cart contents (optional; used for server-side cart implementation if chosen)
  • POST /api/orders/quote — preview totals (subtotal, shipping, tax) for current cart without creating order

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

No admin interface. Cart is a storefront feature.

The seam — why this is core

Core owns the quote engine (POST /api/orders/quote) and checkout validation (POST /api/orders). Theme owns the cart UI and client-side storage logic.

Core owns the interface + honest cart container; shopping cart is core infrastructure, not a support commitment or credential.

Dependencies

  • product management (core) — cart references product ids, which must exist
  • payment-status-tracking — cart leads to checkout, which creates an order with payment_status

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • Add product A (qty 1) to cart; cart shows 1 item, total €25
  • Add product B (qty 2) to cart; cart shows 2 items (different products), total €25 + €30 = €55
  • Add product A again (qty 1); cart shows product A qty 2 (not a new line), total €50 + €30 = €80
  • Remove product B; cart shows 1 item (product A qty 2), total €50
  • Update product A qty to 3; cart total updates to €75
  • Cart persists after page reload (if localStorage-backed)
  • Quote for current cart shows subtotal, shipping methods available, and estimated tax
  • Apply coupon code; quote recalculates with discount applied

Risks

Cart can become invalid: if a product is deleted or a variant goes out of stock after being added to cart, checkout must re-validate and reject with a clear message. If cart size exceeds server limits (e.g., 1000 line items), quote/checkout may fail; theme should warn or cap cart size. If two devices (laptop and phone) both have the same user’s cart in localStorage, they are out of sync — next checkout uses whichever device made the request (no merge). This is by design (simple) but must be documented.

Commercial context

Suggested pricefree (core)
Rival anchorShopify: included; Magento: included

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.