Align Alpine.js base component naming with storefront terminology. Updated across all storefront JS, templates, and documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9.7 KiB
Shop Frontend Troubleshooting
Common issues and solutions for the store shop frontend.
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_inventoryis a calculated property - It sums
quantity - reserved_quantityfrom allinventory_entries - If there are no inventory entries,
available_inventory= 0 - The
canAddToCartcheck fails whenavailable_inventory <= 0
Solution:
# 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:
# 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_abcbut 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 initializessessionIdin itsinit()method- Child components (product, cart) must call parent
init()to getsessionId - If parent init isn't called,
sessionIdisundefined
Solution Already Implemented: The product and cart pages now properly call parent init:
// 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:
🔍 [SHOP] 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.cssnot found/static/css/store/store.cssnot found
- Page is just plain HTML
Root Cause:
Template doesn't extend shop/base.html and has hardcoded non-existent CSS references.
How it Works:
- All shop pages should extend
shop/base.html - Base template includes Tailwind CSS and shop styles
- Standalone HTML pages with
<link>tags won't work
Solution: Refactor template to extend base:
{# BEFORE: Standalone HTML #}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/css/shared/base.css"> ❌
</head>
<body>
<!-- content -->
</body>
</html>
{# AFTER: Extends base #}
{% extends "shop/base.html" %}
{% block title %}My Page{% endblock %}
{% block alpine_data %}myComponent(){% endblock %}
{% block content %}
<!-- content -->
{% endblock %}
Templates Already Fixed:
- ✅
shop/product.html- Refactored to extend base - ✅
shop/cart.html- Refactored to extend base - ✅
shop/products.html- Already extends base - ✅
shop/home.html- Already extends base
Images Not Loading / Placeholder Not Showing
Symptoms:
- Product images show broken image icon
- Console shows 404:
/static/shop/img/placeholder.jpg - OR images point to fake URLs like
https://orion.example.com/images/product-1.jpg
Root Cause:
- Test data has fake image URLs
- Placeholder file was
.jpgbut contained SVG content
How it Works:
- Products have
marketplace_product.image_linkURLs - Template uses fallback:
:src="image || '/static/shop/img/placeholder.svg'" @errorhandler switches to placeholder when image fails to load- Browsers won't render SVG content from
.jpgfiles
Solution Already Implemented:
- Created proper
/static/shop/img/placeholder.svg - Added
@errorhandlers to all image tags:
<img
:src="product.image_link || '/static/shop/img/placeholder.svg'"
@error="$el.src = '/static/shop/img/placeholder.svg'"
alt="Product image"
>
Update Test Data (Optional):
# 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:
/stores/orion/shop/shop/products/4(double/shop/) - Server log shows route not found
Root Cause:
Duplicate /shop prefix in route definitions when router already has prefix.
How it Works:
# Router is mounted with prefix
app.include_router(shop_pages.router, prefix="/shop")
# Route decorator should NOT repeat the prefix
@router.get("/products/{id}") # ✅ Correct
@router.get("/shop/products/{id}") # ❌ Wrong - creates /shop/shop/products/{id}
Solution Already Implemented:
All routes in shop_pages.py have been fixed to remove duplicate /shop/ prefix.
Missing /shop/ in Links
Symptoms:
- Links go to
/stores/orion/productsinstead of/stores/orion/shop/products - 404 errors on navigation
- Footer/header links broken
Root Cause:
Template links missing /shop/ prefix after {{ base_url }}.
Solution:
{# WRONG #}
<a href="{{ base_url }}products">Products</a>
{# CORRECT #}
<a href="{{ base_url }}shop/products">Products</a>
All Templates Fixed:
- ✅
shop/base.html- Header, footer, navigation - ✅
shop/products.html- Product links - ✅
shop/product.html- Breadcrumbs, related products - ✅
shop/cart.html- Continue shopping, checkout - ✅
shop/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:
# Root handler checks for landing page
if has_landing_page():
return render_landing_page()
else:
return redirect("/shop/") # Fallback
Solution:
# Create landing page
python scripts/create_landing_page.py
# Choose store and template
Or Accept Redirect:
The system auto-redirects to /shop/ if no landing page exists. This is normal behavior.
Breadcrumb "Home" Points to Wrong Place
Symptoms:
- Clicking "Home" in breadcrumb goes to shop instead of landing page
- Want "Home" to point to store root (/)
Solution Already Implemented:
{# Breadcrumb Home link points to store root #}
<a href="{{ base_url }}">Home</a>
{# Shop homepage link #}
<a href="{{ base_url }}shop/">Shop</a>
Navigation pattern:
- Logo click →
/shop/(stays in shop 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.sessionIdisundefinedthis.cartCountdoesn't work- Console: "Cannot read property of undefined"
Root Cause:
Child component doesn't call parent init() method.
Solution:
// 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/shop/products/undefined - Console:
productId: undefined
Root Cause:
Product ID not accessible from this.$el.dataset when x-data is on <html> tag.
Solution Already Implemented: Pass via window globals:
{% block extra_scripts %}
<script>
window.PRODUCT_ID = {{ product_id }};
window.STORE_ID = {{ store.id }};
Alpine.data('productDetail', () => ({
productId: window.PRODUCT_ID,
storeId: window.STORE_ID,
// ...
}));
</script>
{% endblock %}
Debugging Tips
Enable Verbose Logging
// In shop-layout.js, the shopLog is already configured
// Check browser console for:
🛒 [SHOP] Shop layout initializing...
🔍 [SHOP] Session ID: session_xxx
[SHOP] Adding to cart: {...}
[SHOP] Cart loaded: 3 items
Check Session ID
// In browser console
localStorage.getItem('cart_session_id')
// Should show: "session_1763765104510_zc866tt5d"
Inspect Product Data
// 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 "shop" and check:
- GET
/api/v1/shop/products- Should return products array - GET
/api/v1/shop/cart/{session_id}- Should return cart items - POST
/api/v1/shop/cart/{session_id}/items- Should return success
Getting Help
- Check this guide first
- Check browser console for errors
- Check server logs for API errors
- Verify database has inventory entries
- Ensure all templates extend
shop/base.html - Check that session ID is initialized
If still stuck, provide:
- Browser console output
- Server log excerpt
- Network tab showing failed requests
- Steps to reproduce