{
  "id": "shopify-style-store",
  "name": "Shopify Style Store",
  "category": "software-builder",
  "tags": ["ecommerce", "store", "cart", "products", "catalog"],
  "description": "Product grid with cart, quantity selector, and checkout summary.",
  "triggers": ["store", "shop", "product grid", "ecommerce", "catalog"],
  "defaultSize": { "w": 6, "h": 6 },
  "source": "const ShopifyStyleStore = () => {\n  const [cart, setCart] = React.useState([]);\n  const [showCart, setShowCart] = React.useState(false);\n  const [search, setSearch] = React.useState('');\n\n  const products = [\n    { id: 1, name: 'Wireless Headphones', price: 79, image: '\uD83C\uDFA7', category: 'Audio', stock: 12 },\n    { id: 2, name: 'Mechanical Keyboard', price: 129, image: '\u2328\uFE0F', category: 'Peripherals', stock: 8 },\n    { id: 3, name: 'USB-C Hub', price: 49, image: '\uD83D\uDCE1', category: 'Accessories', stock: 20 },\n    { id: 4, name: '4K Monitor', price: 349, image: '\uD83D\uDDA5\uFE0F', category: 'Displays', stock: 5 },\n    { id: 5, name: 'Webcam Pro', price: 99, image: '\uD83D\uDCF9', category: 'Video', stock: 15 },\n    { id: 6, name: 'Desk Lamp LED', price: 39, image: '\uD83D\uDCA1', category: 'Office', stock: 30 }\n  ];\n\n  const addToCart = (product, qty = 1) => {\n    setCart(prev => {\n      const existing = prev.find(c => c.id === product.id);\n      if (existing) {\n        return prev.map(c => c.id === product.id ? { ...c, qty: c.qty + qty } : c);\n      }\n      return [...prev, { ...product, qty }];\n    });\n  };\n\n  const updateQty = (id, delta) => {\n    setCart(prev => prev.map(c => {\n      if (c.id !== id) return c;\n      const next = Math.max(1, c.qty + delta);\n      return { ...c, qty: next };\n    }));\n  };\n\n  const removeFromCart = (id) => {\n    setCart(prev => prev.filter(c => c.id !== id));\n  };\n\n  const subtotal = cart.reduce((sum, c) => sum + c.price * c.qty, 0);\n  const tax = Math.round(subtotal * 0.08);\n  const total = subtotal + tax;\n\n  const filtered = products.filter(p => p.name.toLowerCase().includes(search.toLowerCase()));\n\n  const styles = {\n    container: {\n      fontFamily: 'system-ui, -apple-system, sans-serif',\n      background: '#f8fafc',\n      minHeight: '100%',\n      color: '#1e293b'\n    },\n    topbar: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'space-between',\n      padding: '14px 24px',\n      background: '#fff',\n      borderBottom: '1px solid #e2e8f0'\n    },\n    brand: {\n      fontSize: 18,\n      fontWeight: 800\n    },\n    search: {\n      padding: '8px 14px',\n      borderRadius: 8,\n      border: '1px solid #cbd5e1',\n      fontSize: 14,\n      outline: 'none',\n      width: 220\n    },\n    cartBtn: {\n      position: 'relative',\n      padding: '8px 14px',\n      borderRadius: 8,\n      border: '1px solid #cbd5e1',\n      background: '#fff',\n      cursor: 'pointer',\n      fontSize: 14,\n      fontWeight: 600\n    },\n    cartBadge: {\n      position: 'absolute',\n      top: -6,\n      right: -6,\n      background: '#ef4444',\n      color: '#fff',\n      fontSize: 10,\n      fontWeight: 700,\n      width: 18,\n      height: 18,\n      borderRadius: 999,\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center'\n    },\n    main: {\n      display: 'flex'\n    },\n    grid: {\n      flex: 1,\n      padding: 24,\n      display: 'grid',\n      gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))',\n      gap: 16,\n      alignContent: 'start'\n    },\n    product: {\n      background: '#fff',\n      borderRadius: 12,\n      padding: 16,\n      boxShadow: '0 1px 3px rgba(0,0,0,0.06)',\n      border: '1px solid #e2e8f0',\n      textAlign: 'center'\n    },\n    productImg: {\n      fontSize: 48,\n      marginBottom: 10\n    },\n    productName: {\n      fontSize: 14,\n      fontWeight: 700,\n      marginBottom: 4\n    },\n    productCat: {\n      fontSize: 11,\n      color: '#94a3b8',\n      marginBottom: 8,\n      textTransform: 'uppercase',\n      letterSpacing: 0.5\n    },\n    productPrice: {\n      fontSize: 16,\n      fontWeight: 700,\n      color: '#0f172a',\n      marginBottom: 10\n    },\n    qtyRow: {\n      display: 'flex',\n      alignItems: 'center',\n      justifyContent: 'center',\n      gap: 8,\n      marginBottom: 10\n    },\n    qtyBtn: {\n      width: 28,\n      height: 28,\n      borderRadius: 6,\n      border: '1px solid #cbd5e1',\n      background: '#fff',\n      cursor: 'pointer',\n      fontWeight: 700\n    },\n    qtyVal: {\n      fontWeight: 700,\n      fontSize: 14,\n      minWidth: 20\n    },\n    addBtn: {\n      padding: '8px 14px',\n      borderRadius: 8,\n      border: 'none',\n      background: '#2563eb',\n      color: '#fff',\n      fontWeight: 600,\n      cursor: 'pointer',\n      fontSize: 13,\n      width: '100%'\n    },\n    sidebar: {\n      width: 300,\n      background: '#fff',\n      borderLeft: '1px solid #e2e8f0',\n      padding: 20,\n      display: showCart ? 'block' : 'none'\n    },\n    sidebarTitle: {\n      fontSize: 16,\n      fontWeight: 700,\n      marginBottom: 16\n    },\n    cartItem: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: 10,\n      padding: '10px 0',\n      borderBottom: '1px solid #f1f5f9'\n    },\n    cartItemImg: {\n      fontSize: 28\n    },\n    cartItemInfo: {\n      flex: 1\n    },\n    cartItemName: {\n      fontSize: 13,\n      fontWeight: 600\n    },\n    cartItemPrice: {\n      fontSize: 12,\n      color: '#64748b'\n    },\n    cartQty: {\n      display: 'flex',\n      alignItems: 'center',\n      gap: 6\n    },\n    cartQtyBtn: {\n      width: 22,\n      height: 22,\n      borderRadius: 4,\n      border: '1px solid #cbd5e1',\n      background: '#fff',\n      cursor: 'pointer',\n      fontSize: 12,\n      fontWeight: 700\n    },\n    removeBtn: {\n      fontSize: 12,\n      color: '#ef4444',\n      cursor: 'pointer',\n      fontWeight: 600,\n      background: 'none',\n      border: 'none'\n    },\n    summary: {\n      marginTop: 16,\n      paddingTop: 16,\n      borderTop: '2px solid #e2e8f0'\n    },\n    summaryRow: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      fontSize: 14,\n      marginBottom: 8,\n      color: '#475569'\n    },\n    summaryTotal: {\n      display: 'flex',\n      justifyContent: 'space-between',\n      fontSize: 16,\n      fontWeight: 700,\n      marginTop: 8,\n      paddingTop: 8,\n      borderTop: '1px solid #e2e8f0'\n    },\n    checkoutBtn: {\n      marginTop: 14,\n      width: '100%',\n      padding: '10px',\n      borderRadius: 8,\n      border: 'none',\n      background: '#0f172a',\n      color: '#fff',\n      fontWeight: 700,\n      cursor: 'pointer',\n      fontSize: 14\n    },\n    empty: {\n      color: '#94a3b8',\n      fontSize: 14,\n      textAlign: 'center',\n      padding: 24\n    }\n  };\n\n  return (\n    <div style={styles.container}>\n      <div style={styles.topbar}>\n        <div style={styles.brand}>\uD83D\uDED2 Titan Store</div>\n        <input\n          style={styles.search}\n          placeholder=\"Search products...\"\n          value={search}\n          onChange={e => setSearch(e.target.value)}\n        />\n        <button style={styles.cartBtn} onClick={() => setShowCart(!showCart)}>\n          Cart {cart.length > 0 && <span style={styles.cartBadge}>{cart.reduce((a, c) => a + c.qty, 0)}</span>}\n        </button>\n      </div>\n\n      <div style={styles.main}>\n        <div style={styles.grid}>\n          {filtered.map(p => {\n            const [qty, setQty] = React.useState(1);\n            return (\n              <div key={p.id} style={styles.product}>\n                <div style={styles.productImg}>{p.image}</div>\n                <div style={styles.productName}>{p.name}</div>\n                <div style={styles.productCat}>{p.category}</div>\n                <div style={styles.productPrice}>${p.price}</div>\n                <div style={styles.qtyRow}>\n                  <button style={styles.qtyBtn} onClick={() => setQty(Math.max(1, qty - 1))}>-</button>\n                  <span style={styles.qtyVal}>{qty}</span>\n                  <button style={styles.qtyBtn} onClick={() => setQty(qty + 1)}>+</button>\n                </div>\n                <button style={styles.addBtn} onClick={() => addToCart(p, qty)}>Add to Cart</button>\n              </div>\n            );\n          })}\n        </div>\n\n        <div style={styles.sidebar}>\n          <div style={styles.sidebarTitle}>Your Cart</div>\n          {cart.length === 0 ? (\n            <div style={styles.empty}>Your cart is empty.</div>\n          ) : (\n            <>\n              {cart.map(c => (\n                <div key={c.id} style={styles.cartItem}>\n                  <div style={styles.cartItemImg}>{c.image}</div>\n                  <div style={styles.cartItemInfo}>\n                    <div style={styles.cartItemName}>{c.name}</div>\n                    <div style={styles.cartItemPrice}>${c.price} each</div>\n                  </div>\n                  <div style={styles.cartQty}>\n                    <button style={styles.cartQtyBtn} onClick={() => updateQty(c.id, -1)}>-</button>\n                    <span style={{ fontSize: 13, fontWeight: 600 }}>{c.qty}</span>\n                    <button style={styles.cartQtyBtn} onClick={() => updateQty(c.id, 1)}>+</button>\n                  </div>\n                  <button style={styles.removeBtn} onClick={() => removeFromCart(c.id)}>\u2715</button>\n                </div>\n              ))}\n              <div style={styles.summary}>\n                <div style={styles.summaryRow}>\n                  <span>Subtotal</span>\n                  <span>${subtotal}</span>\n                </div>\n                <div style={styles.summaryRow}>\n                  <span>Tax (8%)</span>\n                  <span>${tax}</span>\n                </div>\n                <div style={styles.summaryTotal}>\n                  <span>Total</span>\n                  <span>${total}</span>\n                </div>\n                <button style={styles.checkoutBtn}>Checkout</button>\n              </div>\n            </>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n};\nrender(<ShopifyStyleStore/>);",
  "placeholders": [{ "name": "REPLACE_WITH_STORE_NAME", "description": "Store name shown in the top navigation bar", "default": "Titan Store" }]
}
