@thorprovider/create-storefront 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +119 -0
  2. package/bin/install.js +116 -0
  3. package/commands/sf-add-view.md +21 -0
  4. package/commands/sf-init.md +16 -0
  5. package/commands/sf-theme.md +15 -0
  6. package/commands/sf-view.md +20 -0
  7. package/package.json +40 -0
  8. package/recipes/archetype.schema.json +39 -0
  9. package/recipes/archetypes.json +148 -0
  10. package/recipes/recipe.schema.json +59 -0
  11. package/recipes/recipes.json +90 -0
  12. package/recipes/sections.json +46 -0
  13. package/recipes/validate.mjs +190 -0
  14. package/skills/building-storefronts/SKILL.md +178 -0
  15. package/skills/building-storefronts/references/frontend-integration.md +229 -0
  16. package/skills/json-render-core/SKILL.md +291 -0
  17. package/skills/json-render-next/SKILL.md +194 -0
  18. package/skills/json-render-react/SKILL.md +298 -0
  19. package/skills/json-render-remotion/SKILL.md +111 -0
  20. package/skills/json-render-shadcn/SKILL.md +159 -0
  21. package/skills/json-render-solid/SKILL.md +204 -0
  22. package/skills/nextjs-shadcn/SKILL.md +303 -0
  23. package/skills/nextjs-shadcn/references/architecture.md +499 -0
  24. package/skills/nextjs-shadcn/references/project-setup.md +127 -0
  25. package/skills/nextjs-shadcn/references/shadcn-platform.md +258 -0
  26. package/skills/nextjs-shadcn/references/sidebar.md +274 -0
  27. package/skills/nextjs-shadcn/references/styling.md +555 -0
  28. package/skills/sf-scaffold/SKILL.md +118 -0
  29. package/skills/sf-theme-gen/SKILL.md +44 -0
  30. package/skills/sf-view-gen/SKILL.md +94 -0
  31. package/skills/shadcn-component-discovery/SKILL.md +273 -0
  32. package/skills/shadcn-component-discovery/references/registries.md +226 -0
  33. package/skills/shadcn-theming/SKILL.md +104 -0
  34. package/skills/shadcn-theming/references/templates/theme-setup.md +109 -0
  35. package/skills/shadcn-theming/references/theming-guide.md +90 -0
  36. package/skills/storefront-best-practices/SKILL.md +421 -0
  37. package/skills/storefront-best-practices/reference/components/breadcrumbs.md +123 -0
  38. package/skills/storefront-best-practices/reference/components/cart-popup.md +189 -0
  39. package/skills/storefront-best-practices/reference/components/country-selector.md +298 -0
  40. package/skills/storefront-best-practices/reference/components/footer.md +112 -0
  41. package/skills/storefront-best-practices/reference/components/hero.md +241 -0
  42. package/skills/storefront-best-practices/reference/components/megamenu.md +239 -0
  43. package/skills/storefront-best-practices/reference/components/navbar.md +397 -0
  44. package/skills/storefront-best-practices/reference/components/popups.md +221 -0
  45. package/skills/storefront-best-practices/reference/components/product-card.md +125 -0
  46. package/skills/storefront-best-practices/reference/components/product-reviews.md +217 -0
  47. package/skills/storefront-best-practices/reference/components/product-slider.md +174 -0
  48. package/skills/storefront-best-practices/reference/components/search.md +101 -0
  49. package/skills/storefront-best-practices/reference/connecting-to-backend.md +391 -0
  50. package/skills/storefront-best-practices/reference/design.md +388 -0
  51. package/skills/storefront-best-practices/reference/features/promotions.md +307 -0
  52. package/skills/storefront-best-practices/reference/features/wishlist.md +230 -0
  53. package/skills/storefront-best-practices/reference/layouts/account.md +380 -0
  54. package/skills/storefront-best-practices/reference/layouts/cart.md +316 -0
  55. package/skills/storefront-best-practices/reference/layouts/checkout.md +486 -0
  56. package/skills/storefront-best-practices/reference/layouts/home-page.md +264 -0
  57. package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +231 -0
  58. package/skills/storefront-best-practices/reference/layouts/product-details.md +527 -0
  59. package/skills/storefront-best-practices/reference/layouts/product-listing.md +520 -0
  60. package/skills/storefront-best-practices/reference/layouts/static-pages.md +356 -0
  61. package/skills/storefront-best-practices/reference/medusa.md +307 -0
  62. package/skills/storefront-best-practices/reference/mobile-responsiveness.md +183 -0
  63. package/skills/storefront-best-practices/reference/seo.md +195 -0
  64. package/templates/app/app/[[...slug]]/page.tsx +17 -0
  65. package/templates/app/app/[[...slug]]/renderer.tsx +10 -0
  66. package/templates/app/app/globals.css +101 -0
  67. package/templates/app/app/layout.tsx +35 -0
  68. package/templates/app/lib/__STOREFRONT__/catalog.ts +132 -0
  69. package/templates/app/lib/__STOREFRONT__/handlers.ts +33 -0
  70. package/templates/app/lib/__STOREFRONT__/registry.tsx +134 -0
  71. package/templates/app/lib/__STOREFRONT__/runtime.ts +25 -0
  72. package/templates/app/lib/__STOREFRONT__/spec/home.ts +62 -0
  73. package/templates/app/lib/__STOREFRONT__/spec/index.ts +59 -0
  74. package/templates/app/lib/__STOREFRONT__/spec/types.ts +14 -0
  75. package/templates/app/lib/__STOREFRONT__/state.ts +35 -0
@@ -0,0 +1,527 @@
1
+ # Product Detail Page Layout
2
+
3
+ ## Contents
4
+
5
+ - [Overview](#overview)
6
+ - [Layout Structure](#layout-structure)
7
+ - [Price Display and Medusa Integration](#price-display-and-medusa-integration)
8
+ - [Variant Selection (Critical)](#variant-selection-critical)
9
+ - [Stock Availability](#stock-availability)
10
+ - [Add to Cart Behavior](#add-to-cart-behavior)
11
+ - [Product Details Organization](#product-details-organization)
12
+ - [Related Products Strategy](#related-products-strategy)
13
+ - [Trust Signals and Conversion](#trust-signals-and-conversion)
14
+ - [Mobile Optimization](#mobile-optimization)
15
+ - [Checklist](#checklist)
16
+
17
+ ## Overview
18
+
19
+ Most critical page for conversion. Customers make purchase decisions here based on product information, images, reviews, and trust signals.
20
+
21
+ ### Key Requirements
22
+
23
+ - High-quality product images with zoom capability
24
+ - Clear price display (handle variant price changes)
25
+ - Variant selection (size, color, material)
26
+ - Stock availability indicators
27
+ - Prominent "Add to Cart" with proper feedback
28
+ - Product details (description, specifications)
29
+ - Customer reviews and ratings
30
+ - Related product recommendations
31
+ - Trust signals (shipping, returns, secure checkout)
32
+ - Mobile-optimized (60%+ traffic)
33
+
34
+ ### Routing Pattern
35
+
36
+ **CRITICAL: Always use dynamic routes, NEVER static pages.**
37
+
38
+ Product detail pages must use dynamic routes that accept a parameter (handle, slug, or ID):
39
+
40
+ **Correct examples:**
41
+ - Next.js App Router: `app/products/[handle]/page.tsx`
42
+ - Next.js Pages Router: `pages/products/[handle].tsx`
43
+ - SvelteKit: `routes/products/[handle]/+page.svelte`
44
+ - TanStack Start: `routes/products/$handle.tsx`
45
+ - Remix: `routes/products.$handle.tsx`
46
+
47
+ **Wrong examples:**
48
+ - ❌ `pages/products/blue-shirt.tsx` (static file per product)
49
+ - ❌ `pages/products/red-shoes.tsx` (doesn't scale)
50
+
51
+ Fetch product data in the dynamic route based on the handle/ID parameter from the URL.
52
+
53
+ ## Layout Structure
54
+
55
+ **Desktop (two-column):**
56
+ - Left: Product images (50-60% width)
57
+ - Right: Product info, variants, add to cart (40-50%)
58
+ - Below: Product details, reviews, related products (full-width)
59
+
60
+ **Mobile (stacked):**
61
+ - Images at top (full-width, swipeable)
62
+ - Product info below (title, price, rating)
63
+ - Variants and add to cart
64
+ - Accordion for product details
65
+ - Reviews section
66
+ - Related products
67
+ - Sticky "Add to Cart" bar at bottom
68
+
69
+ **Sticky sidebar option (desktop):**
70
+ - Product info column stays visible during scroll
71
+ - Add to cart always accessible
72
+ - Useful for long product descriptions
73
+ - Improves conversion
74
+
75
+ ## Price Display
76
+
77
+ ### Standard Price Display
78
+
79
+ **Current price:**
80
+ - Large, bold font (28-36px)
81
+ - Currency symbol included ($49.99)
82
+ - Primary color or black
83
+
84
+ **Sale pricing:**
85
+ - Original price with strikethrough: ~~$79.99~~ $49.99
86
+ - Sale price in red or brand color
87
+ - "Save X%" badge nearby
88
+ - Example: Save 37%
89
+
90
+ **Variant price changes:**
91
+ - **When no variant selected**: Show "From $X" where X is the minimum variant price across all variants
92
+ - **When variant selected**: Update price dynamically to show the exact variant price
93
+ - No page reload required
94
+ - Show price change clearly (highlight briefly on change)
95
+ - Example: Product with variants priced at $29.99, $34.99, $39.99 → Show "From $29.99" initially
96
+
97
+ ### Medusa Pricing (CRITICAL)
98
+
99
+ **Important difference from Stripe:**
100
+ - Medusa stores prices as-is (e.g., 49.99)
101
+ - Display directly: If API returns 49.99, show $49.99
102
+ - **DON'T divide by 100** (unlike Stripe which stores in cents)
103
+ - Example: Medusa 49.99 → Display $49.99 (NOT $0.4999)
104
+
105
+ **Multi-currency (Medusa):**
106
+ - Medusa supports multi-region pricing
107
+ - Display price in user's region currency
108
+ - Fetch pricing from selected region
109
+ - Show currency code (usd, eur, etc.)
110
+
111
+ ## Variant Selection (Critical)
112
+
113
+ This is a complex ecommerce-specific challenge. Variants affect price, stock, and images.
114
+
115
+ ### Variant Complexity
116
+
117
+ **Key challenges:**
118
+ - Multiple variant types (size, color, material)
119
+ - Variant availability varies (some sizes out of stock)
120
+ - Prices may differ by variant
121
+ - Images change by color variant
122
+ - Stock levels per variant
123
+ - Combinations may not exist (size M + color Red might not exist)
124
+
125
+ **Fetch from backend:**
126
+ ```typescript
127
+ // Get all variants for product
128
+ // Change this based on the backend integrated
129
+ const product = await fetch(`/products/${id}?fields=*variants`)
130
+ // Returns variants with: id, sku, options, calculated_price, inventory_quantity
131
+ ```
132
+
133
+ ### Variant Selection Patterns
134
+
135
+ **Use Button Group when:**
136
+ - 2-8 options per variant type
137
+ - Size selection (XS, S, M, L, XL)
138
+ - Simple color options (5-6 colors)
139
+ - Users need to see all options at once
140
+
141
+ **Benefits:**
142
+ - Visible options (no click to reveal)
143
+ - Faster selection
144
+ - Clear visual feedback
145
+ - Better UX
146
+
147
+ **Use Dropdown when:**
148
+ - 10+ options per variant type
149
+ - Material/style options with long names
150
+ - Space-constrained layouts
151
+ - Mobile optimization needed
152
+
153
+ **Benefits:**
154
+ - Saves space
155
+ - Works better for many options
156
+ - Mobile-friendly
157
+
158
+ **Use Visual Swatches when:**
159
+ - Color or pattern variations
160
+ - Material with visual differences
161
+ - Visual is key to decision
162
+ - Fashion, home decor, customizable products
163
+
164
+ **Implementation:**
165
+ - Circular/square swatches (40-48px)
166
+ - Border on selected
167
+ - Show product image in that color when selected
168
+ - Color name on hover
169
+ - Gray out unavailable colors
170
+
171
+ ### Variant Selection Flow
172
+
173
+ **Critical sequence:**
174
+ 1. User selects first variant type (e.g., Color: Blue)
175
+ 2. **Update available options** for other variant types
176
+ 3. Show only size options available for Blue color
177
+ 4. Gray out/disable unavailable combinations
178
+ 5. Update price if variant price differs
179
+ 6. Update main product image to show selected variant
180
+ 7. Update stock availability
181
+ 8. Enable/disable "Add to Cart" based on availability
182
+
183
+ **Example: Two variants (Color + Size)**
184
+ ```typescript
185
+ // When color selected
186
+ // Change this based on the backend integrated
187
+ onColorSelect(color) {
188
+ // Find selected variant
189
+ const selectededVariant = product.variants.find((variant) => variant.options?.every(
190
+ (optionValue) => optionValue.id === selectedOptions[optionValue.option_id!]
191
+ ))
192
+
193
+ // Check if size is selected and update price
194
+ if (selectededVariant) {
195
+ const variant = findVariant(color, selectedSize)
196
+ updatePrice(variant.price)
197
+ updateStock(variant.inventory_quantity)
198
+ }
199
+ }
200
+ ```
201
+
202
+ ### Validation and Error Handling
203
+
204
+ **Prevent adding without selection:**
205
+ - Disable "Add to Cart" until all required variants selected
206
+ - Or: Show error message "Please select a size"
207
+ - Highlight missing selection (red border around options)
208
+ - Scroll to variant selection on error
209
+
210
+ **Handle out of stock variants:**
211
+ - Gray out unavailable options
212
+ - "Out of stock" text on hover
213
+ - Don't allow selection of out of stock variants
214
+ - Suggest alternative variants if available
215
+
216
+ **Handle variant not found:**
217
+ - When combination doesn't exist (Size M + Color Red)
218
+ - Disable second option when first selected
219
+ - Show only valid combinations
220
+ - Or: Show "This combination is not available"
221
+
222
+ ## Stock Availability
223
+
224
+ **Display patterns:**
225
+
226
+ **In stock:**
227
+ - Green indicator (✓ or dot)
228
+ - "In stock" or "Available"
229
+ - Quantity if low: "Only 3 left"
230
+ - Encourages urgency without being pushy
231
+
232
+ **Out of stock:**
233
+ - Red indicator (✗ or dot)
234
+ - "Out of stock" message
235
+ - Disable "Add to Cart" button (grayed out)
236
+ - Offer "Notify me when available"
237
+ - Email capture for restock notifications (if supported by backend)
238
+
239
+ **Low stock warning:**
240
+ - "Only X left in stock"
241
+ - Shows scarcity (increases urgency)
242
+ - Typically show when <= 5 items
243
+ - Orange/yellow color
244
+
245
+ **Pre-order:**
246
+ - "Pre-order now" status
247
+ - Expected availability date: "Ships on [Date]"
248
+ - Different button text: "Pre-order" instead of "Add to Cart"
249
+ - Charge now or later (specify)
250
+
251
+ **Backend integration:**
252
+ ```typescript
253
+ // Fetch stock for selected variant
254
+ const stock = selectedVariant.inventory_quantity
255
+
256
+ if (stock === 0) {
257
+ showOutOfStock()
258
+ } else if (stock <= 5) {
259
+ showLowStock(stock) // "Only 3 left"
260
+ } else {
261
+ showInStock()
262
+ }
263
+ ```
264
+
265
+ ## Add to Cart Behavior
266
+
267
+ **Button states:**
268
+ - Default: Enabled (after variant selected)
269
+ - Hover: Slight color change or scale
270
+ - Loading: Spinner inside button (during API call)
271
+ - Success: Checkmark briefly, then revert
272
+ - Disabled: Grayed out (no variant or out of stock)
273
+
274
+ **Click behavior (Critical):**
275
+ 1. Show loading state (disable button, show spinner)
276
+ 2. Call API to add item to cart (backend)
277
+ 3. **Optimistic UI**: Update cart count immediately (before API response)
278
+ 4. Show success feedback (toast, checkmark, or cart popup)
279
+ 5. Update cart count in navbar header
280
+ 6. **DON'T navigate away** - stay on product page
281
+ 7. Handle errors: restore count if API fails
282
+
283
+ **Success feedback options:**
284
+ - Toast notification: "Added to cart" (top-right)
285
+ - Cart popup: Show mini cart with items (see cart-popup.md)
286
+ - Checkmark in button briefly, then revert
287
+ - All three combined (checkmark + toast or cart popup)
288
+
289
+ **Error handling:**
290
+ ```typescript
291
+ async function addToCart(variantId, quantity) {
292
+ try {
293
+ // Optimistic update
294
+ updateCartCountUI(+quantity)
295
+
296
+ // API call
297
+ // Change this based on the backend integrated
298
+ await fetch(`/store/carts/${cartId}/line-items`, {
299
+ method: 'POST',
300
+ body: JSON.stringify({ variant_id: variantId, quantity })
301
+ })
302
+
303
+ // Success feedback
304
+ showToast('Added to cart')
305
+ showCartPopup() // Optional
306
+ } catch (error) {
307
+ // Revert optimistic update
308
+ updateCartCountUI(-quantity)
309
+
310
+ // Show error
311
+ if (error.message === 'OUT_OF_STOCK') {
312
+ showError('Sorry, this item is now out of stock')
313
+ updateStockStatus('out_of_stock')
314
+ } else {
315
+ showError('Failed to add to cart. Please try again.')
316
+ }
317
+ }
318
+ }
319
+ ```
320
+
321
+ **Buy Now button (optional):**
322
+ - Skip cart, go directly to checkout
323
+ - Useful for: high-value items, single-item stores, decisive customers
324
+ - Secondary button below "Add to Cart"
325
+ - Text: "Buy Now" or "Buy It Now"
326
+ - Add to cart + redirect to checkout in one action
327
+
328
+ ## Product Details Organization
329
+
330
+ ### Decision: Tabs vs Accordion
331
+
332
+ **Use Tabs (desktop) when:**
333
+ - 3-5 distinct sections
334
+ - Each section has substantial content
335
+ - Users may want to compare sections
336
+ - Desktop has screen space
337
+ - Examples: Description, Specifications, Shipping, Reviews
338
+
339
+ **Use Accordion (mobile) always:**
340
+ - Saves vertical space
341
+ - Users expand what they need
342
+ - Standard mobile pattern
343
+ - Collapses after reading
344
+
345
+ **Hybrid approach (recommended):**
346
+ - Tabs on desktop (horizontal navigation)
347
+ - Accordion on mobile (vertical expansion)
348
+ - Same content, different presentation
349
+ - Best of both worlds
350
+
351
+ ### Common Sections
352
+
353
+ **Description:**
354
+ - Product overview (2-4 paragraphs)
355
+ - Key features (bullet points)
356
+ - Use cases
357
+ - Materials and craftsmanship
358
+
359
+ **Specifications:**
360
+ - Technical details (table format)
361
+ - Dimensions, weight, materials
362
+ - Care instructions
363
+ - Compatibility information
364
+
365
+ **Shipping & Returns:**
366
+ - Shipping options and costs
367
+ - Delivery timeframes
368
+ - Return policy (30 days, 60 days)
369
+ - Return process
370
+ - Link to full policy page
371
+
372
+ **Reviews:**
373
+ - Embedded in tab/accordion
374
+ - Or: Separate section below
375
+ - Filter by rating, sort by date
376
+ - Review submission form
377
+
378
+ ## Related Products Strategy
379
+
380
+ **Types of recommendations:**
381
+
382
+ **"You May Also Like" (Similar products):**
383
+ - Same category, similar price point
384
+ - Algorithm: category match + price range
385
+ - Goal: Show alternatives if unsure about current product
386
+
387
+ **"Frequently Bought Together" (Complementary):**
388
+ - Products commonly purchased together
389
+ - Algorithm: order history analysis
390
+ - Goal: Increase average order value
391
+ - Example: Phone + Case + Screen Protector
392
+ - Show bundle discount if available
393
+
394
+ **"Recently Viewed" (Browsing history):**
395
+ - User's browsing history (session or logged-in)
396
+ - Helps users return to products they liked
397
+ - Goal: Reduce decision paralysis
398
+
399
+ **"Customers Also Viewed":**
400
+ - Products viewed by others who viewed this
401
+ - Algorithm: co-viewing patterns
402
+ - Goal: Discovery and alternatives
403
+
404
+ ### Display Pattern
405
+
406
+ **Product slider:**
407
+ - 4-6 products visible (desktop)
408
+ - 2-3 visible (mobile)
409
+ - Horizontal scrolling (swipe on mobile)
410
+ - Product cards: image, title, price, rating
411
+ - Optional: Quick "Add to Cart" on hover
412
+
413
+ **Placement:**
414
+ - Below product details and reviews
415
+ - Above footer
416
+ - Full-width section
417
+ - Clear heading for each type
418
+
419
+ **Backend integration:**
420
+ ```typescript
421
+ // Fetch recommendations
422
+ // Change this based on the backend integrated
423
+ const recommendations = await fetch(`/products/${id}/recommendations`)
424
+ // Returns: similar, bought_together, recently_viewed
425
+ ```
426
+
427
+ ## Trust Signals and Conversion
428
+
429
+ **Essential trust signals:**
430
+
431
+ **Near Add to Cart:**
432
+ - Free shipping badge (if applicable)
433
+ - Free returns icon + text
434
+ - Secure checkout icon
435
+ - Money-back guarantee
436
+ - Warranty information (if applicable)
437
+
438
+ **Below product title:**
439
+ - Customer rating and review count (4.8 ★ 324 reviews)
440
+ - Link to reviews section
441
+ - "Best seller" or "Top rated" badge
442
+
443
+ **Payment methods:**
444
+ - Accepted payment icons (Visa, Mastercard, PayPal, Apple Pay)
445
+ - Small icons (40px)
446
+ - Below "Add to Cart" or in footer
447
+ - Shows payment options available
448
+
449
+ **For new/unknown brands:**
450
+ - Customer testimonials
451
+ - "Join 10,000+ happy customers"
452
+ - Security badges (if legitimate - don't fake)
453
+ - Social proof (Instagram photos, user content)
454
+ - Clear contact information
455
+
456
+ **For high-value products:**
457
+ - Detailed specifications
458
+ - Professional photography
459
+ - Video demonstrations
460
+ - Warranty details prominently displayed
461
+ - Customer service contact visible
462
+
463
+ ## Mobile Optimization
464
+
465
+ **Critical mobile patterns:**
466
+
467
+ **Sticky "Add to Cart" bar:**
468
+ - Fixed at bottom of screen
469
+ - Always accessible (no scrolling needed)
470
+ - Shows: Price + "Add to Cart" button
471
+ - Appears after scrolling past fold
472
+ - Higher conversion rates
473
+
474
+ **Image gallery:**
475
+ - Full-width swipeable carousel
476
+ - Pinch to zoom
477
+ - Dot indicators (1/5, 2/5)
478
+ - Tap to open full-screen view
479
+
480
+ **Variant selection:**
481
+ - Large touch targets (44-48px)
482
+ - Visual swatches easier than dropdowns
483
+ - Clear selected state
484
+ - Error messages visible
485
+
486
+ **Accordion for details:**
487
+ - Description, Specs, Shipping as accordion
488
+ - Starts collapsed (save space)
489
+ - User expands what they need
490
+ - Clear expand/collapse indicators
491
+
492
+ **Reviews section:**
493
+ - Expandable (start with 2-3 reviews)
494
+ - "Show more" button
495
+ - Filter by rating
496
+ - Star rating distribution chart
497
+
498
+ ## Checklist
499
+
500
+ **Essential product detail page features:**
501
+
502
+ - [ ] High-quality product images with zoom
503
+ - [ ] Price displayed correctly (Medusa: use value as-is, not divided)
504
+ - [ ] Price shows "From $X" when no variant selected (X = minimum variant price)
505
+ - [ ] Variant selection required before adding to cart
506
+ - [ ] Variant selection updates: price, stock, image
507
+ - [ ] Disable unavailable variant options (gray out)
508
+ - [ ] Stock availability indicator (in stock, low stock, out of stock)
509
+ - [ ] "Only X left" shown when stock is low (<=5)
510
+ - [ ] Add to Cart disabled until variant selected
511
+ - [ ] Optimistic UI update (cart count updates immediately)
512
+ - [ ] Success feedback (toast, cart popup, or checkmark)
513
+ - [ ] Stay on product page after adding (don't navigate away)
514
+ - [ ] Error handling (out of stock, API failure)
515
+ - [ ] Product description and specifications
516
+ - [ ] Customer reviews and ratings
517
+ - [ ] Related products recommendations (similar, bought together)
518
+ - [ ] Trust signals (free shipping, returns, secure checkout)
519
+ - [ ] Payment method icons displayed
520
+ - [ ] Breadcrumb navigation
521
+ - [ ] Mobile: Swipeable image gallery
522
+ - [ ] Mobile: Accordion for product details
523
+ - [ ] Mobile: Sticky Add to Cart bar (optional but effective)
524
+ - [ ] Tabs on desktop, accordion on mobile (hybrid)
525
+ - [ ] Fast loading (<2s, optimize images)
526
+ - [ ] Keyboard accessible (tab through options, enter to add)
527
+ - [ ] ARIA labels on variant selection (role="group", aria-label)