# Storefront Troubleshooting Common issues and solutions for the store storefront. ## Cart and Product Issues ### Products Cannot Be Added to Cart **Symptoms:** - "Add to Cart" button is disabled - No response when clicking "Add to Cart" - Console shows `canAddToCart: false` **Root Cause:** Products have `available_inventory: 0` because the `inventory` table is empty. **How it Works:** - Product's `available_inventory` is a calculated property - It sums `quantity - reserved_quantity` from all `inventory_entries` - If there are no inventory entries, `available_inventory` = 0 - The `canAddToCart` check fails when `available_inventory <= 0` **Solution:** ```bash # Create inventory entries for all products python scripts/create_inventory.py ``` This script: - Finds all products without inventory entries - Creates inventory with 100 units in "Main Warehouse" - Can be run multiple times (only creates missing entries) **Verify Fix:** ```python # Check a product's inventory from app.core.database import SessionLocal from models.database.product import Product db = SessionLocal() product = db.query(Product).first() print(f"Available inventory: {product.available_inventory}") # Should show: Available inventory: 100 ``` ### Cart is Empty After Adding Products **Symptoms:** - Success toast appears: "1 item(s) added to cart!" - Cart count in header doesn't update - Cart page shows 0 items - Console shows `session_1234_abc` but API returns empty cart **Root Cause:** Session ID not properly initialized in Alpine.js components. **How it Works:** - Cart uses session ID stored in localStorage as `cart_session_id` - `storefrontLayoutData()` base component initializes `sessionId` in its `init()` method - Child components (product, cart) must call parent `init()` to get `sessionId` - If parent init isn't called, `sessionId` is `undefined` **Solution Already Implemented:** The product and cart pages now properly call parent init: ```javascript // In product.html and cart.html async init() { // Call parent init to set up sessionId if (baseData.init) { baseData.init.call(this); } // Now sessionId is available await this.loadCart(); } ``` **Verify Fix:** Open browser console and check for: ``` 🔍 [STOREFRONT] Session ID: session_1763765104510_zc866tt5d ``` If you see `undefined`, the parent init isn't being called properly. ## Styling and Layout Issues ### Page Has No Styling / CSS 404 Errors **Symptoms:** - Page displays with no styling - Console shows 404 errors: - `/static/css/shared/base.css` not found - `/static/css/store/store.css` not found - Page is just plain HTML **Root Cause:** Template doesn't extend `storefront/base.html` and has hardcoded non-existent CSS references. **How it Works:** - All storefront pages should extend `storefront/base.html` - Base template includes Tailwind CSS and storefront styles - Standalone HTML pages with `` tags won't work **Solution:** Refactor template to extend base: ```jinja2 {# BEFORE: Standalone HTML #} {# AFTER: Extends base #} {% extends "storefront/base.html" %} {% block title %}My Page{% endblock %} {% block alpine_data %}myComponent(){% endblock %} {% block content %} {% endblock %} ``` **Templates Already Fixed:** - ✅ `storefront/product.html` - Refactored to extend base - ✅ `storefront/cart.html` - Refactored to extend base - ✅ `storefront/products.html` - Already extends base - ✅ `storefront/home.html` - Already extends base ### Images Not Loading / Placeholder Not Showing **Symptoms:** - Product images show broken image icon - Console shows 404: `/static/storefront/img/placeholder.jpg` - OR images point to fake URLs like `https://orion.example.com/images/product-1.jpg` **Root Cause:** 1. Test data has fake image URLs 2. Placeholder file was `.jpg` but contained SVG content **How it Works:** - Products have `marketplace_product.image_link` URLs - Template uses fallback: `:src="image || '/static/storefront/img/placeholder.svg'"` - `@error` handler switches to placeholder when image fails to load - Browsers won't render SVG content from `.jpg` files **Solution Already Implemented:** - Created proper `/static/storefront/img/placeholder.svg` - Added `@error` handlers to all image tags: ```html Product image ``` **Update Test Data (Optional):** ```python # Replace fake URLs with real placeholder images import sqlite3 conn = sqlite3.connect('orion.db') cursor = conn.cursor() cursor.execute(""" UPDATE marketplace_products SET image_link = NULL WHERE image_link LIKE '%example.com%' """) conn.commit() ``` ## Navigation and Routing Issues ### Product Detail Page Returns 404 **Symptoms:** - Clicking product shows 404 error - URL is: `/storefront/orion/storefront/products/4` (double `/storefront/`) - Server log shows route not found **Root Cause:** Duplicate `/storefront` prefix in route definitions when router already has prefix. **How it Works:** ```python # Router is mounted with prefix app.include_router(storefront_pages.router, prefix="/storefront") # Route decorator should NOT repeat the prefix @router.get("/products/{id}") # ✅ Correct @router.get("/storefront/products/{id}") # ❌ Wrong - creates /storefront/storefront/products/{id} ``` **Solution Already Implemented:** All routes in `storefront_pages.py` have been fixed to remove duplicate `/storefront/` prefix. ### Missing `/storefront/` in Links **Symptoms:** - Links go to `/storefront/orion/products` instead of correct storefront URLs - 404 errors on navigation - Footer/header links broken **Root Cause:** Template links missing `/storefront/` prefix after `{{ base_url }}`. **Solution:** ```jinja2 {# WRONG #} Products {# CORRECT #} Products ``` **All Templates Fixed:** - ✅ `storefront/base.html` - Header, footer, navigation - ✅ `storefront/products.html` - Product links - ✅ `storefront/product.html` - Breadcrumbs, related products - ✅ `storefront/cart.html` - Continue shopping, checkout - ✅ `storefront/errors/404.html` - All fallback links ## Landing Page Issues ### Store Root Shows 404 **Symptoms:** - `http://localhost:8000/stores/orion/` returns 404 - `/` path not found **Root Cause:** No landing page created for store. **How it Works:** ```python # Root handler checks for landing page if has_landing_page(): return render_landing_page() else: return redirect("/storefront/") # Fallback ``` **Solution:** ```bash # Create landing page python scripts/create_landing_page.py # Choose store and template ``` **Or Accept Redirect:** The system auto-redirects to `/storefront/` if no landing page exists. This is normal behavior. ### Breadcrumb "Home" Points to Wrong Place **Symptoms:** - Clicking "Home" in breadcrumb goes to storefront instead of landing page - Want "Home" to point to store root (/) **Solution Already Implemented:** ```jinja2 {# Breadcrumb Home link points to store root #} Home {# Storefront homepage link #} Storefront ``` Navigation pattern: - **Logo click** → `/storefront/` (stays in storefront for convenience) - **Breadcrumb "Home"** → `/` (returns to landing page/root) - **Header "Home" link** → `/` (returns to landing page/root) ## Alpine.js / JavaScript Issues ### Component Data Not Available **Symptoms:** - `this.sessionId` is `undefined` - `this.cartCount` doesn't work - Console: "Cannot read property of undefined" **Root Cause:** Child component doesn't call parent `init()` method. **Solution:** ```javascript // Store reference to parent const baseData = storefrontLayoutData(); return { ...baseData, // Child properties items: [], // Call parent init async init() { if (baseData.init) { baseData.init.call(this); } // Now parent properties are initialized await this.loadData(); } }; ``` ### Product ID is Undefined **Symptoms:** - API call: `/api/v1/storefront/products/undefined` - Console: `productId: undefined` **Root Cause:** Product ID not accessible from `this.$el.dataset` when `x-data` is on `` tag. **Solution Already Implemented:** Pass via window globals: ```html {% block extra_scripts %} {% endblock %} ``` ## Debugging Tips ### Enable Verbose Logging ```javascript // In storefront-layout.js, the storefrontLog is already configured // Check browser console for: 🛒 [STOREFRONT] Storefront layout initializing... 🔍 [STOREFRONT] Session ID: session_xxx [STOREFRONT] Adding to cart: {...} [STOREFRONT] Cart loaded: 3 items ``` ### Check Session ID ```javascript // In browser console localStorage.getItem('cart_session_id') // Should show: "session_1763765104510_zc866tt5d" ``` ### Inspect Product Data ```javascript // In browser console on product page Alpine.$data(document.querySelector('[x-data]')).product // Shows full product object with inventory ``` ### Check API Responses In browser Network tab, filter by "storefront" and check: - GET `/api/v1/storefront/products` - Should return products array - GET `/api/v1/storefront/cart/{session_id}` - Should return cart items - POST `/api/v1/storefront/cart/{session_id}/items` - Should return success ## Getting Help 1. Check this guide first 2. Check browser console for errors 3. Check server logs for API errors 4. Verify database has inventory entries 5. Ensure all templates extend `storefront/base.html` 6. Check that session ID is initialized If still stuck, provide: - Browser console output - Server log excerpt - Network tab showing failed requests - Steps to reproduce