Initial commit
This commit is contained in:
421
.agents/skills/storefront-best-practices/SKILL.md
Normal file
421
.agents/skills/storefront-best-practices/SKILL.md
Normal file
@@ -0,0 +1,421 @@
|
||||
---
|
||||
name: storefront-best-practices
|
||||
description: ALWAYS use this skill when working on ecommerce storefronts, online stores, shopping sites. Use for ANY storefront component including checkout pages, cart, payment flows, product pages, product listings, navigation, homepage, or ANY page/component in a storefront. CRITICAL for adding checkout, implementing cart, integrating Medusa backend, or building any ecommerce functionality. Framework-agnostic (Next.js, SvelteKit, TanStack Start, React, Vue). Provides patterns, decision frameworks, backend integration guidance.
|
||||
---
|
||||
|
||||
# Ecommerce Storefront Best Practices
|
||||
|
||||
Comprehensive guidance for building modern, high-converting ecommerce storefronts covering UI/UX patterns, component design, layout structures, SEO optimization, and mobile responsiveness.
|
||||
|
||||
## When to Apply
|
||||
|
||||
**ALWAYS load this skill when working on ANY storefront task:**
|
||||
|
||||
- **Adding checkout page/flow** - Payment, shipping, order placement
|
||||
- **Implementing cart** - Cart page, cart popup, add to cart functionality
|
||||
- **Building product pages** - Product details, product listings, product grids
|
||||
- **Creating navigation** - Navbar, megamenu, footer, mobile menu
|
||||
- **Integrating Medusa backend** - SDK setup, cart, products, payment
|
||||
- **Any storefront component** - Homepage, search, filters, account pages
|
||||
- Building new ecommerce storefronts from scratch
|
||||
- Improving existing shopping experiences and conversion rates
|
||||
- Optimizing for usability, accessibility, and SEO
|
||||
- Designing mobile-responsive ecommerce experiences
|
||||
|
||||
**Example prompts that should trigger this skill:**
|
||||
- "Add a checkout page"
|
||||
- "Implement shopping cart"
|
||||
- "Create product listing page"
|
||||
- "Connect to Medusa backend"
|
||||
- "Add navigation menu"
|
||||
- "Build homepage for store"
|
||||
|
||||
## CRITICAL: Load Reference Files When Needed
|
||||
|
||||
**⚠️ ALWAYS load `reference/design.md` BEFORE creating ANY UI component**
|
||||
- Discovers existing design tokens (colors, fonts, spacing, patterns)
|
||||
- Prevents introducing inconsistent styles
|
||||
- Provides guardrails for maintaining brand consistency
|
||||
- **Required for every component, not just new storefronts**
|
||||
|
||||
**Load these references based on what you're implementing:**
|
||||
|
||||
- **Starting a new storefront?** → MUST load `reference/design.md` first to discover user preferences
|
||||
- **Connecting to backend API?** → MUST load `reference/connecting-to-backend.md` first
|
||||
- **Connecting to Medusa backend?** → MUST load `reference/medusa.md` for SDK setup, pricing, regions, and Medusa patterns
|
||||
- **Implementing homepage?** → MUST load `reference/components/navbar.md`, `reference/components/hero.md`, `reference/components/footer.md`, and `reference/layouts/home-page.md`
|
||||
- **Implementing navigation?** → MUST load `reference/components/navbar.md` and optionally `reference/components/megamenu.md`
|
||||
- **Building product listing?** → MUST load `reference/layouts/product-listing.md` first
|
||||
- **Building product details?** → MUST load `reference/layouts/product-details.md` first
|
||||
- **Implementing checkout?** → MUST load `reference/layouts/checkout.md` first
|
||||
- **Optimizing for SEO?** → MUST load `reference/seo.md` first
|
||||
- **Optimizing for mobile?** → MUST load `reference/mobile-responsiveness.md` first
|
||||
|
||||
**Minimum requirement:** Load at least 1-2 reference files relevant to your specific task before implementing.
|
||||
|
||||
## Planning and Implementation Workflow
|
||||
|
||||
**IMPORTANT: If you create a plan for implementing storefront features, include the following in your plan:**
|
||||
|
||||
When implementing each component, page, layout, or feature in the plan:
|
||||
1. **Refer back to this skill** before starting implementation
|
||||
2. **Load relevant reference files** listed above for the specific component/page you're building
|
||||
3. **Follow the patterns and guidance** in the reference files
|
||||
4. **Check common mistakes** sections to avoid known pitfalls
|
||||
|
||||
**Example plan structure:**
|
||||
|
||||
```
|
||||
Task 1: Implement Navigation
|
||||
- Load reference/components/navbar.md
|
||||
- Follow patterns from navbar.md (dynamic category fetching, cart visibility, etc.)
|
||||
- Refer to skill for common mistakes (e.g., hardcoding categories)
|
||||
|
||||
Task 2: Implement Product Listing Page
|
||||
- Load reference/layouts/product-listing.md
|
||||
- Follow pagination/filtering patterns from product-listing.md
|
||||
- Use reference/components/product-card.md for product grid items
|
||||
- Check skill for backend integration guidance
|
||||
|
||||
Task 3: Implement Checkout Flow
|
||||
- Load reference/layouts/checkout.md
|
||||
- Load reference/medusa.md for Medusa payment integration
|
||||
- Follow component architecture recommendations (separate step components)
|
||||
- Refer to skill for payment method fetching requirements
|
||||
```
|
||||
|
||||
**Why this matters:**
|
||||
- Plans provide high-level strategy
|
||||
- Reference files provide detailed implementation patterns
|
||||
- Skill file contains critical mistakes to avoid
|
||||
- Following this workflow ensures consistency and best practices
|
||||
|
||||
## Critical Ecommerce-Specific Patterns
|
||||
|
||||
### Accessibility
|
||||
- **CRITICAL: Cart count updates require `aria-live="polite"`** - Screen readers won't announce without it
|
||||
- Ensure keyboard navigation for all cart/checkout interactions
|
||||
|
||||
### Mobile
|
||||
- **Sticky bottom elements MUST use `env(safe-area-inset-bottom)`** - iOS home indicator will cut off purchase buttons otherwise
|
||||
- 44px minimum touch targets for cart actions, variant selectors, quantity buttons
|
||||
|
||||
### Performance
|
||||
- **ALWAYS add `loading="lazy"` to product images below fold** - Don't rely on browser defaults
|
||||
- Optimize product images for mobile (<500KB) - Most ecommerce traffic is mobile
|
||||
|
||||
### Conversion Optimization
|
||||
- Clear CTAs throughout shopping flow
|
||||
- Minimal friction in checkout (guest checkout if supported)
|
||||
- Trust signals (reviews, security badges, return policy) near purchase buttons
|
||||
- Clear pricing and shipping information upfront
|
||||
|
||||
### SEO
|
||||
- **Product schema (JSON-LD) required** - Critical for Google Shopping and rich snippets
|
||||
- Use [PageSpeed Insights](https://pagespeed.web.dev/) to measure Core Web Vitals
|
||||
|
||||
### Visual Design
|
||||
- **NEVER use emojis** in storefront UI - Use icons or images instead (unprofessional, accessibility issues)
|
||||
|
||||
### Backend Integration
|
||||
- **Backend detection**: If in monorepo, check for backend directory. If unsure, ask user which backend is used.
|
||||
- **NEVER hardcode dynamic content**: Always fetch categories, regions, products, shipping options, etc. from backend - they change frequently
|
||||
- Never assume API structure - verify endpoints and data formats
|
||||
|
||||
### ⚠️ CRITICAL: Backend SDK Method Verification Workflow
|
||||
|
||||
**YOU MUST FOLLOW THIS EXACT WORKFLOW BEFORE WRITING CODE THAT CONNECTS TO BACKEND:**
|
||||
|
||||
**Step 1: PAUSE - Do NOT write code yet**
|
||||
- You are about to write code that calls a backend API or SDK method (e.g., Medusa SDK, REST API, GraphQL)
|
||||
- **STOP** - Do not proceed to code without verification
|
||||
|
||||
**Step 2: QUERY the documentation or MCP server**
|
||||
- **If MCP server available**: Query it for the exact method (for example, medusa MCP)
|
||||
- **If no MCP server**: Search official documentation
|
||||
- **Find**: Exact method name, parameters, return type
|
||||
|
||||
**Step 3: VERIFY what you found**
|
||||
- State out loud to the user: "I need to verify the correct method for [operation]. Let me check [MCP server/documentation]."
|
||||
- Show the user what you found: "According to [source], the method is `sdk.store.cart.methodName(params)`"
|
||||
- Confirm the method signature and parameters
|
||||
|
||||
**Step 4: ONLY THEN write the code**
|
||||
- Now you can write code using the verified method
|
||||
- Use the exact signature you found
|
||||
|
||||
**Step 5: CHECK for TypeScript errors**
|
||||
- After writing the code, check for any TypeScript/type errors related to the SDK
|
||||
- If you see type errors on SDK methods, it means you used an incorrect method name or wrong parameters
|
||||
- **Type errors are a sign you didn't verify correctly** - Go back to Step 2
|
||||
|
||||
**THIS IS NOT OPTIONAL - THIS IS MANDATORY ERROR PREVENTION**
|
||||
|
||||
**It is a CRITICAL ERROR to:**
|
||||
- ❌ Write code that calls backend APIs/SDKs without explicitly querying docs/MCP first
|
||||
- ❌ Guess method names or parameters
|
||||
- ❌ Ignore TypeScript errors on SDK methods (errors indicate incorrect method usage)
|
||||
- ❌ Copy examples from this skill without verification (examples may be outdated)
|
||||
- ❌ Assume SDK methods match REST API endpoints
|
||||
|
||||
**For Medusa specifically:**
|
||||
- **Medusa pricing**: Display prices as-is - DO NOT divide by 100 (unlike Stripe, Medusa stores prices in display format)
|
||||
- **Medusa MCP server**: https://docs.medusajs.com/mcp - Recommend setup if not installed
|
||||
- Load `reference/medusa.md` for Medusa-specific patterns (regions, pricing, etc.)
|
||||
|
||||
### Routing Patterns
|
||||
- **ALWAYS use dynamic routes** for products and categories - NEVER create static pages for individual items
|
||||
- Product pages: Use dynamic routes like `/products/[handle]` or `/products/$handle`, NOT `/products/shirt.tsx`
|
||||
- Category pages: Use dynamic routes like `/categories/[handle]` or `/categories/$handle`, NOT `/categories/women.tsx`
|
||||
- Framework-specific patterns:
|
||||
- **Next.js App Router**: `app/products/[handle]/page.tsx` or `app/products/[id]/page.tsx`
|
||||
- **Next.js Pages Router**: `pages/products/[handle].tsx`
|
||||
- **SvelteKit**: `routes/products/[handle]/+page.svelte`
|
||||
- **TanStack Start**: `routes/products/$handle.tsx`
|
||||
- **Remix**: `routes/products.$handle.tsx`
|
||||
- Why: Dynamic routes scale to any number of products/categories without creating individual files
|
||||
- Static routes are unmaintainable and don't scale (imagine creating 1000 product files)
|
||||
|
||||
## Pattern Selection Guides
|
||||
|
||||
When you need to choose between implementation patterns, load the relevant reference file:
|
||||
|
||||
- **Checkout strategy** (single-page vs multi-step) → Load `reference/layouts/checkout.md`
|
||||
- **Navigation strategy** (dropdown vs megamenu) → Load `reference/components/navbar.md` and `reference/components/megamenu.md`
|
||||
- **Product listing strategy** (pagination vs infinite scroll vs load more) → Load `reference/layouts/product-listing.md`
|
||||
- **Search strategy** (autocomplete vs filters vs natural language) → Load `reference/components/search.md`
|
||||
- **Mobile vs desktop priorities** → Load `reference/mobile-responsiveness.md`
|
||||
- **Variant selection** (text vs swatches vs configurator) → Load `reference/layouts/product-details.md`
|
||||
- **Cart pattern** (popup vs drawer vs page navigation) → Load `reference/components/cart-popup.md` and `reference/layouts/cart.md`
|
||||
- **Trust signals strategy** → Load `reference/layouts/product-details.md` and `reference/layouts/checkout.md`
|
||||
|
||||
Each reference file contains decision frameworks with specific criteria to help you choose the right pattern for your context.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### General
|
||||
|
||||
```
|
||||
reference/connecting-to-backend.md - Framework detection, API setup, backend integration patterns
|
||||
reference/medusa.md - Medusa SDK integration, pricing, regions, TypeScript types
|
||||
reference/design.md - User preferences, brand identity, design systems
|
||||
reference/seo.md - Meta tags, structured data, Core Web Vitals
|
||||
reference/mobile-responsiveness.md - Mobile-first design, responsive breakpoints, touch interactions
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
```
|
||||
reference/components/navbar.md - Desktop/mobile navigation, logo, menu, cart icon, load for ALL pages
|
||||
reference/components/megamenu.md - Category organization, featured products, mobile alternatives
|
||||
reference/components/cart-popup.md - Add-to-cart feedback, mini cart display
|
||||
reference/components/country-selector.md - Country/region selection, currency, pricing, Medusa regions
|
||||
reference/components/breadcrumbs.md - Category hierarchy, structured data markup
|
||||
reference/components/search.md - Search input, autocomplete, results, filters
|
||||
reference/components/product-reviews.md - Review display, rating aggregation, submission
|
||||
reference/components/hero.md - Hero layouts, CTA placement, image optimization
|
||||
reference/components/popups.md - Newsletter signup, discount popups, exit-intent
|
||||
reference/components/footer.md - Content organization, navigation, social media, load for ALL pages
|
||||
reference/components/product-card.md - Product images, pricing, add to cart, badges
|
||||
reference/components/product-slider.md - Carousel implementation, mobile swipe, accessibility
|
||||
```
|
||||
|
||||
### Layouts
|
||||
|
||||
```
|
||||
reference/layouts/home-page.md - Hero, featured categories, product listings
|
||||
reference/layouts/product-listing.md - Grid/list views, filters, sorting, pagination
|
||||
reference/layouts/product-details.md - Image gallery, variant selection, related products
|
||||
reference/layouts/cart.md - Cart items, quantity updates, promo codes
|
||||
reference/layouts/checkout.md - Multi-step/single-page, address forms, payment
|
||||
reference/layouts/order-confirmation.md - Order number, summary, delivery info
|
||||
reference/layouts/account.md - Dashboard, order history, address book
|
||||
reference/layouts/static-pages.md - FAQ, about, contact, shipping/returns policies
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
```
|
||||
reference/features/wishlist.md - Add to wishlist, wishlist page, move to cart
|
||||
reference/features/promotions.md - Promotional banners, discount codes, sale badges
|
||||
```
|
||||
|
||||
## Common Implementation Patterns
|
||||
|
||||
### Starting a New Storefront
|
||||
|
||||
**IMPORTANT: For each step below, load the referenced files BEFORE implementing that step.**
|
||||
|
||||
```
|
||||
1. Discovery Phase → Read design.md for user preferences
|
||||
2. Foundation Setup → Read connecting-to-backend.md (or medusa.md for Medusa), mobile-responsiveness.md, seo.md
|
||||
3. Core Components → Implement navbar.md, footer.md
|
||||
4. Home Page → Read home-page.md
|
||||
5. Product Browsing → Read product-listing.md, product-card.md, search.md
|
||||
6. Product Details → Read product-details.md, product-reviews.md
|
||||
7. Cart & Checkout → Read cart-popup.md, cart.md, checkout.md, order-confirmation.md
|
||||
8. User Account → Read account.md
|
||||
9. Additional Features → Read wishlist.md, promotions.md
|
||||
10. Optimization → SEO audit (seo.md), mobile testing (mobile-responsiveness.md)
|
||||
```
|
||||
|
||||
Even if you create an implementation plan, refer back to the skill and load relevant reference files when implementing each step.
|
||||
|
||||
### Shopping Flow Pattern
|
||||
|
||||
```
|
||||
Browse → View → Cart → Checkout
|
||||
|
||||
Browse: home-page.md → product-listing.md
|
||||
View: product-details.md + product-reviews.md
|
||||
Cart: cart-popup.md → cart.md
|
||||
Checkout: checkout.md → order-confirmation.md
|
||||
```
|
||||
|
||||
### Component Selection Guide
|
||||
|
||||
**For product grids and filtering** → `product-listing.md` and `product-card.md`
|
||||
**For product cards** → `product-card.md`
|
||||
**For navigation** → `navbar.md` and `megamenu.md`
|
||||
**For search functionality** → `search.md`
|
||||
**For checkout flow** → `checkout.md`
|
||||
**For promotions and sales** → `promotions.md`
|
||||
|
||||
## Design Considerations
|
||||
|
||||
Before implementing, consider:
|
||||
|
||||
1. **User preferences** - Read `design.md` to discover design style preferences
|
||||
2. **Brand identity** - Colors, typography, tone that match the brand
|
||||
3. **Target audience** - B2C vs B2B, demographics, device usage
|
||||
4. **Product type** - Fashion vs electronics vs groceries affect layout choices
|
||||
5. **Business requirements** - Multi-currency, multi-language, region-specific
|
||||
6. **Backend system** - API structure affects component implementation
|
||||
|
||||
## Integration with Medusa
|
||||
|
||||
[Medusa](https://medusajs.com) is a modern, flexible ecommerce backend. Consider Medusa when:
|
||||
|
||||
- Building a new ecommerce storefront
|
||||
- Need a headless commerce solution
|
||||
- Want built-in support for multi-region, multi-currency
|
||||
- Need powerful promotion and discount engine
|
||||
- Require flexible product modeling
|
||||
|
||||
For detailed Medusa integration guidance, see `reference/medusa.md`. For general backend patterns, see `reference/connecting-to-backend.md`.
|
||||
|
||||
### Framework Agnostic
|
||||
|
||||
All guidance is framework-agnostic. Examples use React/TypeScript where code demonstrations are helpful, but patterns apply to:
|
||||
|
||||
- Next.js
|
||||
- SvelteKit
|
||||
- Tanstack Start
|
||||
- Any modern frontend framework
|
||||
|
||||
## Minimum Viable Features
|
||||
|
||||
**Mandatory for launch (core shopping flow):**
|
||||
- Navbar with cart, categories, search
|
||||
- Product listing with filtering and pagination
|
||||
- Product details with variant selection
|
||||
- Add to cart functionality
|
||||
- Cart page with item management
|
||||
- Checkout flow (shipping, payment, review)
|
||||
- Order confirmation page
|
||||
|
||||
**Nice-to-have (add if time permits):**
|
||||
- Related products recommendations
|
||||
- Product reviews and ratings
|
||||
- Wishlist functionality
|
||||
- Image zoom on product pages
|
||||
- Bottom navigation on mobile
|
||||
- Mega-menu for navigation
|
||||
- Newsletter signup
|
||||
- Product comparison
|
||||
- Quick view modals
|
||||
|
||||
**User-dependent (ask before implementing):**
|
||||
- Guest checkout vs login-required
|
||||
- Account dashboard features
|
||||
- Multi-language support
|
||||
- Multi-currency support
|
||||
- Live chat support
|
||||
|
||||
## Top Ecommerce Mistakes to Avoid
|
||||
|
||||
Before implementing, watch out for these common ecommerce-specific pitfalls:
|
||||
|
||||
**1. Cart and Navigation Mistakes**
|
||||
- ❌ Hiding cart indicator in mobile hamburger menu (keep always visible)
|
||||
- ❌ Not showing real-time cart count updates
|
||||
- ❌ **CRITICAL: Missing `aria-live="polite"` on cart count** - Screen readers won't announce cart updates without it
|
||||
- ❌ Not displaying variant details (size, color, etc.) in cart popup - only showing product title
|
||||
- ❌ Megamenu closes when hovering over dropdown content (must stay open when hovering trigger OR dropdown)
|
||||
- ❌ **CRITICAL: Megamenu positioning errors** - Three common mistakes:
|
||||
- ❌ Navbar doesn't have `position: relative` (megamenu won't position correctly)
|
||||
- ❌ Megamenu positioned relative to trigger button instead of navbar (use `absolute left-0` on megamenu)
|
||||
- ❌ Megamenu doesn't span full width (must use `right-0` or `w-full`, not just `w-auto`)
|
||||
- ❌ Hardcoding categories, featured products, or any dynamic content instead of fetching from backend
|
||||
- ❌ No clear indication of current page in category navigation
|
||||
|
||||
**2. Product Browsing Mistakes**
|
||||
- ❌ Creating static routes for products/categories (use dynamic routes like `/products/[handle]` instead of `/products/shirt.tsx`)
|
||||
- ❌ Missing "no products found" empty state with helpful suggestions
|
||||
- ❌ No loading indicators while fetching products
|
||||
- ❌ Pagination without SEO-friendly URLs (for search engines)
|
||||
- ❌ Filter selections that don't persist on page reload
|
||||
|
||||
**3. Product Details Mistakes**
|
||||
- ❌ Enabling "Add to Cart" before variant selection (size, color, etc.)
|
||||
- ❌ Missing product images optimization (large uncompressed images)
|
||||
- ❌ Navigating away from product page after adding to cart (stay on page)
|
||||
- ❌ Using emojis in UI instead of icons or images (unprofessional, accessibility issues)
|
||||
|
||||
**4. Design and Consistency Mistakes**
|
||||
- ❌ **CRITICAL: Not loading `reference/design.md` before creating ANY UI component** - Leads to inconsistent colors, fonts, and styles
|
||||
- ❌ Introducing new colors without checking existing theme first
|
||||
- ❌ Adding new fonts without verifying what's already used
|
||||
- ❌ Using arbitrary Tailwind values when theme tokens exist
|
||||
- ❌ Not detecting Tailwind version (v3 vs v4) - Causes syntax errors
|
||||
|
||||
**5. Checkout and Conversion Mistakes**
|
||||
- ❌ Requiring account creation to checkout (offer guest checkout if backend supports it)
|
||||
- ❌ Not fetching payment methods from backend - assuming available payment options or skipping payment method selection
|
||||
- ❌ Overly complex multi-step checkout (4+ steps kills conversion) - Optimal is 3 steps: Shipping Info, Delivery Method + Payment, Review
|
||||
- ❌ Missing trust signals (secure checkout badge, return policy link)
|
||||
- ❌ Not handling out-of-stock errors gracefully during checkout
|
||||
|
||||
**6. Mobile Experience Mistakes**
|
||||
- ❌ Touch targets smaller than 44x44px (buttons, links, form fields)
|
||||
- ❌ Desktop-style hover menus on mobile (use tap/click instead)
|
||||
- ❌ Not optimizing images for mobile (loading huge desktop images)
|
||||
- ❌ Missing mobile-specific patterns (bottom nav, drawer filters)
|
||||
|
||||
**7. Performance and SEO Mistakes**
|
||||
- ❌ Missing structured data (Product schema) for SEO
|
||||
- ❌ No explicit image lazy loading (don't assume browser defaults) - Always add `loading="lazy"` to images below the fold
|
||||
- ❌ Missing meta tags and Open Graph for social sharing
|
||||
- ❌ Not optimizing Core Web Vitals (LCP, FID, CLS) - Use [PageSpeed Insights](https://pagespeed.web.dev/) or Lighthouse to measure
|
||||
|
||||
**8. Backend Integration Mistakes**
|
||||
- ❌ **ERROR: Writing code that calls backend APIs/SDKs without following the 5-step verification workflow** - You MUST: 1) PAUSE, 2) QUERY docs/MCP, 3) VERIFY with user, 4) Write code, 5) CHECK for type errors
|
||||
- ❌ **ERROR: Ignoring TypeScript errors on SDK methods** - Type errors mean you used wrong method names or parameters. Go back and verify with docs/MCP
|
||||
- ❌ **ERROR: Guessing API method names, SDK methods, or parameters** - Always verify exact method signatures before use
|
||||
- ❌ **ERROR: Not using Medusa MCP server when available** - If using Medusa backend, always query MCP server for methods
|
||||
- ❌ **ERROR: Copying code examples without verifying they're current** - Examples may be outdated, always verify first
|
||||
- ❌ Not detecting which backend is being used (check monorepo, ask user if unsure)
|
||||
- ❌ Assuming API structure without checking backend documentation or MCP server
|
||||
- ❌ Hardcoding dynamic content (categories, regions, products, etc.) instead of fetching from backend
|
||||
- ❌ Defining custom types for Medusa entities instead of using `@medusajs/types` package
|
||||
- ❌ Initializing Medusa SDK without publishable API key (required for multi-region stores and product pricing)
|
||||
- ❌ Fetching Medusa products without passing `region_id` query parameter (causes missing or incorrect pricing)
|
||||
- ❌ Showing all countries in Medusa checkout - should only show countries from cart's region
|
||||
- ❌ Dividing Medusa prices by 100 (Medusa stores prices as-is, not in cents like Stripe)
|
||||
- ❌ Missing Vite SSR config for Medusa SDK (add `ssr.noExternal: ['@medusajs/js-sdk']` to vite.config.ts)
|
||||
- ❌ Running Medusa storefront on port other than 8000 (causes CORS errors - Medusa backend expects port 8000 by default)
|
||||
- ❌ Not handling loading, error, and empty states for API calls
|
||||
- ❌ Making API calls on client-side that should be server-side (SEO, security)
|
||||
- ❌ Not implementing proper error messages ("Error occurred" vs "Product out of stock")
|
||||
- ❌ Missing cache invalidation (stale product data, prices, inventory)
|
||||
- ❌ **Not clearing cart state after order is placed** - Cart popup shows old items because cart wasn't reset from Context/localStorage/cache
|
||||
@@ -0,0 +1,123 @@
|
||||
# Breadcrumbs Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [When to Use Breadcrumbs](#when-to-use-breadcrumbs)
|
||||
- [Ecommerce Breadcrumb Patterns](#ecommerce-breadcrumb-patterns)
|
||||
- [Mobile Breadcrumbs](#mobile-breadcrumbs)
|
||||
- [SEO Structured Data](#seo-structured-data)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Breadcrumbs show the user's location within the site hierarchy (Home → Category → Subcategory → Product). Critical for ecommerce navigation and SEO.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build breadcrumbs with separators and links. This guide focuses on ecommerce-specific patterns.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Show full path from homepage to current page
|
||||
- Each level clickable (except current page)
|
||||
- Position below navbar, above page title
|
||||
- Include structured data for SEO (JSON-LD)
|
||||
- Mobile-optimized (back link pattern)
|
||||
|
||||
## When to Use Breadcrumbs
|
||||
|
||||
**Use for:**
|
||||
- Product pages (Home → Category → Subcategory → Product)
|
||||
- Category pages (Home → Category → Subcategory)
|
||||
- Deep site hierarchies (3+ levels)
|
||||
- Large catalogs with many categories
|
||||
|
||||
**Don't use for:**
|
||||
- Homepage (no parent pages)
|
||||
- Flat site structures (1-2 levels)
|
||||
- Checkout flow (linear, not hierarchical)
|
||||
- Search results (not hierarchical)
|
||||
|
||||
## Ecommerce Breadcrumb Patterns
|
||||
|
||||
### Product Page Breadcrumbs
|
||||
|
||||
**Standard pattern:**
|
||||
- Home / Category / Subcategory / Product Name
|
||||
- Example: Home / Electronics / Laptops / Gaming Laptop Pro
|
||||
|
||||
**Key considerations:**
|
||||
- All levels except product name are clickable
|
||||
- Product name is current page (non-clickable, darker text)
|
||||
- Shows product's location in catalog
|
||||
|
||||
**Multiple category membership:**
|
||||
- If product in multiple categories, choose primary/canonical
|
||||
- Match category in URL or navigation path
|
||||
- Be consistent across site
|
||||
|
||||
### Category Page Breadcrumbs
|
||||
|
||||
**Standard pattern:**
|
||||
- Home / Parent Category / Current Category
|
||||
- Example: Home / Electronics / Laptops
|
||||
|
||||
**Current category:**
|
||||
- Non-clickable (plain text)
|
||||
- Visually distinct from links (darker or bold)
|
||||
|
||||
### Path Construction
|
||||
|
||||
**Hierarchy:**
|
||||
- Start with "Home" (or home icon)
|
||||
- Follow category hierarchy
|
||||
- End with current page
|
||||
- Maximum 5-6 levels (keep shallow)
|
||||
|
||||
**URL alignment:**
|
||||
- Breadcrumb path should match URL hierarchy
|
||||
- Consistent naming between URLs and breadcrumbs
|
||||
- Example: `/categories/electronics/laptops` → "Home / Electronics / Laptops"
|
||||
|
||||
## Mobile Breadcrumbs
|
||||
|
||||
### Mobile Pattern: Collapse to Back Link
|
||||
|
||||
**Recommended approach:**
|
||||
- Show only previous level as back link
|
||||
- Back arrow icon (←) + parent page name
|
||||
- Example: "← Gaming Laptops"
|
||||
|
||||
**Why:**
|
||||
- Saves vertical space on mobile
|
||||
- Clear affordance (back navigation)
|
||||
- Simpler than full breadcrumb trail
|
||||
- Mobile users have device back button
|
||||
|
||||
**Alternative: Truncated path**
|
||||
- Show "Home ... Current Page"
|
||||
- Hide middle levels
|
||||
- Balances space and context
|
||||
|
||||
## SEO Structured Data
|
||||
|
||||
**BreadcrumbList schema (CRITICAL)**: Add JSON-LD structured data. Breadcrumbs appear in search results, improves CTR, helps search engines understand site structure.
|
||||
|
||||
**Implementation**: schema.org BreadcrumbList with items array. Each item has position (1, 2, 3...), name, and URL. See seo.md for schema details.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Positioned below navbar, above page title
|
||||
- [ ] Full path shown (Home → Category → Product)
|
||||
- [ ] All levels clickable except current page
|
||||
- [ ] Current page visually distinct (non-clickable, darker)
|
||||
- [ ] Clear separators (›, /, > or chevron)
|
||||
- [ ] Mobile: Back link pattern ("← Category")
|
||||
- [ ] Structured data (JSON-LD BreadcrumbList)
|
||||
- [ ] Semantic HTML (`<nav aria-label="Breadcrumb">`)
|
||||
- [ ] `aria-current="page"` on current item
|
||||
- [ ] Keyboard accessible (tab through links)
|
||||
- [ ] Truncate long labels (20-30 characters max)
|
||||
- [ ] Consistent with navigation labels
|
||||
- [ ] Maximum 5-6 levels deep
|
||||
@@ -0,0 +1,189 @@
|
||||
# Cart Popup Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [When to Show Cart Popup](#when-to-show-cart-popup)
|
||||
- [Layout Patterns](#layout-patterns)
|
||||
- [Cart Display](#cart-display)
|
||||
- [Actions and CTAs](#actions-and-ctas)
|
||||
- [Empty State](#empty-state)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Cart popup (mini cart/cart drawer) shows quick cart overview without navigating away. Opens from cart icon click or after adding items.
|
||||
|
||||
**⚠️ CRITICAL: Always display variant details (size, color, material, etc.) in cart popup, not just product titles.**
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build modals, dialogs, and overlays. This focuses on ecommerce-specific patterns.
|
||||
|
||||
**Cart popup vs full cart page:**
|
||||
- Popup: Quick overview, fast checkout path, continue shopping easily
|
||||
- Full page: Detailed review, promo codes, complex operations
|
||||
- **Recommended**: Both - popup for speed, full cart page for details
|
||||
|
||||
## When to Show Cart Popup
|
||||
|
||||
**Trigger options:**
|
||||
|
||||
1. **On cart icon click** (always) - Click cart icon in navbar opens popup
|
||||
2. **After adding to cart** (recommended) - Auto-open popup when item added, confirms action, allows checkout or continue shopping
|
||||
3. **Hover cart icon** (desktop only, optional) - Quick peek on hover. Can be accidental, not recommended.
|
||||
|
||||
**Add-to-cart feedback alternatives:**
|
||||
- Show popup (most common) - Immediate confirmation, clear path to checkout
|
||||
- Toast only (less intrusive) - Small notification, user clicks cart icon to see details
|
||||
- Navigate to cart page (traditional) - Goes directly to full cart page, less common now
|
||||
|
||||
## Layout Patterns
|
||||
|
||||
**Two common patterns:**
|
||||
|
||||
**1. Dropdown (recommended for simplicity):**
|
||||
- Drops down from cart icon, positioned below navbar
|
||||
- Width: 280-320px, max height with scroll
|
||||
- No backdrop overlay (click outside to close)
|
||||
- Better for few items, simpler implementation
|
||||
|
||||
**2. Slide-in drawer (more prominent):**
|
||||
- Slides from right, full height, width 320-400px (desktop) or 80-90% (mobile)
|
||||
- Semi-transparent backdrop overlay (click to close)
|
||||
- Better for multiple items or complex carts
|
||||
|
||||
**Both patterns have:**
|
||||
- Header: Title + item count + close button (optional for dropdown)
|
||||
- Scrollable content: List of cart items
|
||||
- Sticky footer: Subtotal + action buttons (Checkout, View Cart)
|
||||
|
||||
## Cart Display
|
||||
|
||||
**Fetch cart data from backend:**
|
||||
- Cart ID from localStorage
|
||||
- Line items (products, variants, quantities, prices)
|
||||
- Cart totals (subtotal, tax, shipping)
|
||||
- See connecting-to-backend.md for backend integration
|
||||
|
||||
**When to fetch:**
|
||||
- On app initialization (update cart icon badge)
|
||||
- On popup open (show loading state)
|
||||
- After cart updates (add/remove/change quantity)
|
||||
|
||||
**State management:**
|
||||
- Store cart data globally (React Context or TanStack Query)
|
||||
- Persist cart ID in localStorage
|
||||
- Optimistic UI updates (update immediately, revert on error)
|
||||
- **CRITICAL: Clear cart state after order is placed** - See connecting-to-backend.md for cart cleanup pattern
|
||||
- Common issue: Cart popup shows old items after checkout because cart state wasn't cleared
|
||||
- See connecting-to-backend.md for cart state patterns
|
||||
|
||||
**Cart item display:**
|
||||
|
||||
**CRITICAL: Always show variant details (size, color, material, etc.) for each cart item.**
|
||||
|
||||
Without variant details, users can't confirm they added the correct variant. This is especially critical when products have multiple options.
|
||||
|
||||
- Product image (60-80px thumbnail)
|
||||
- Product title (truncated to 2 lines)
|
||||
- **Variant details (REQUIRED)**: Size, color, material, or other variant options
|
||||
- Format: "Size: Large, Color: Black" or "Large / Black"
|
||||
- Show ALL selected variant options, not just product title
|
||||
- Display below title, smaller text (gray)
|
||||
- Quantity controls (+/- buttons, debounce 300-500ms)
|
||||
- Unit price and total price (line item total = price × quantity)
|
||||
- Remove button (X icon, no confirmation needed)
|
||||
|
||||
**Why variant details are critical:**
|
||||
- User confirmation: "Did I add the right size?"
|
||||
- Prevents cart abandonment from uncertainty
|
||||
- Allows corrections before checkout
|
||||
- Essential for products with multiple variants (clothing, shoes, configurable products)
|
||||
|
||||
## Actions and CTAs
|
||||
|
||||
**Cart summary display:**
|
||||
- Subtotal (sum of all items)
|
||||
- Shipping and tax: "Calculated at checkout" or actual amount
|
||||
- Total: Bold and prominent
|
||||
|
||||
**Free shipping indicator (optional):**
|
||||
- "Add $25 more for free shipping" with progress bar
|
||||
- Encourages larger orders, updates as cart changes
|
||||
|
||||
**Promo codes:**
|
||||
- Usually NOT in cart popup (too cramped)
|
||||
- Reserve for full cart page
|
||||
- Exception: Simple code input if space permits
|
||||
|
||||
**Action buttons:**
|
||||
1. **Checkout** (primary) - Most prominent, high contrast (brand color), navigates to checkout
|
||||
2. **View Cart** (secondary) - Outline or subtle, navigates to full cart page
|
||||
|
||||
Both buttons full-width, 44-48px height on mobile.
|
||||
|
||||
## Empty State
|
||||
|
||||
Show icon/illustration + "Your cart is empty" + "Continue Shopping" button. Centered, friendly, minimal design.
|
||||
|
||||
## Loading and Error States
|
||||
|
||||
**On popup open**: Show skeleton/placeholder while fetching (avoid blank screen)
|
||||
|
||||
**During updates**:
|
||||
- Quantity changes: Inline spinner, disable controls, debounce 300-500ms
|
||||
- Item removal: Fade out animation, disable remove button during request
|
||||
- Add to cart: Loading indicator on button ("Adding...")
|
||||
|
||||
**Error handling**:
|
||||
- Network errors: Show retry option, don't close popup
|
||||
- Invalid cart ID: Create new cart automatically
|
||||
- Out of stock: Disable quantity increase, show message
|
||||
- Revert optimistic updates on failure
|
||||
|
||||
**Animations**: Smooth transitions (250-350ms), slide-in drawer, backdrop fade-in/out. Highlight newly added items.
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Dropdown on mobile:**
|
||||
- Full-width (100% minus margins)
|
||||
- Max height 60-70% viewport, scrollable
|
||||
- Tap outside to close
|
||||
|
||||
**Drawer on mobile:**
|
||||
- 85-95% screen width or full screen
|
||||
- Slides from right or bottom
|
||||
- Swipe to close gesture supported
|
||||
- Backdrop overlay
|
||||
|
||||
**Mobile adjustments:**
|
||||
- Large touch targets (44-48px minimum)
|
||||
- Full-width action buttons (48-52px height)
|
||||
- Smaller images (60px), truncate titles
|
||||
- Sticky footer with actions
|
||||
- Large close button (44x44px)
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
- [ ] Opens on cart icon click
|
||||
- [ ] Dropdown (280-320px) or drawer (320-400px) layout
|
||||
- [ ] Close button or click outside to close
|
||||
- [ ] Backdrop overlay if drawer
|
||||
- [ ] **CRITICAL: Cart items show variant details (size, color, etc.) - not just product title**
|
||||
- [ ] Cart items with image, title, variant options, quantity, prices
|
||||
- [ ] Quantity controls (+/- buttons, debounced)
|
||||
- [ ] Remove item button
|
||||
- [ ] Subtotal displayed
|
||||
- [ ] Checkout button (primary)
|
||||
- [ ] View Cart button (secondary)
|
||||
- [ ] Empty state with "Continue Shopping" CTA
|
||||
- [ ] Loading states (skeleton/spinner)
|
||||
- [ ] Smooth animations (250-350ms)
|
||||
- [ ] Mobile: Full-width dropdown or 85-95% drawer
|
||||
- [ ] Touch targets 44-48px minimum
|
||||
- [ ] `role="dialog"` and `aria-modal="true"`
|
||||
- [ ] ARIA labels on cart button ("Shopping cart with 3 items")
|
||||
- [ ] Keyboard accessible (focus trap, Escape closes, return focus)
|
||||
- [ ] Screen reader announcements (item added/removed)
|
||||
- [ ] Real-time cart count badge updates
|
||||
@@ -0,0 +1,298 @@
|
||||
# Country Selector Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [When to Implement](#when-to-implement)
|
||||
- [UI Patterns](#ui-patterns)
|
||||
- [State Management](#state-management)
|
||||
- [Backend Integration](#backend-integration)
|
||||
- [Detection and Defaults](#detection-and-defaults)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Country selector allows customers to choose their country/region, which determines currency, pricing, available products, shipping options, payment methods, and localized content.
|
||||
|
||||
### Key Ecommerce Functions
|
||||
|
||||
- Display prices in correct currency
|
||||
- Show country-specific product availability
|
||||
- Apply region-specific promotions and discounts
|
||||
- Calculate accurate shipping costs and delivery times
|
||||
- Enable appropriate payment methods
|
||||
- Display localized content and language
|
||||
|
||||
### Purpose
|
||||
|
||||
**Why country/region selection matters:**
|
||||
- Prices vary by region (currency, taxes, import fees)
|
||||
- Product availability differs by market
|
||||
- Shipping methods and costs are region-specific
|
||||
- Legal requirements vary (privacy, consumer protection)
|
||||
- Payment methods differ by country
|
||||
- Improves user experience with relevant content
|
||||
|
||||
## When to Implement
|
||||
|
||||
**Implement country selector when:**
|
||||
- Backend supports multiple countries or regions
|
||||
- Selling to multiple countries or regions
|
||||
- Prices vary by location (currency, taxes)
|
||||
- International shipping with different rates
|
||||
- Region-specific product catalogs
|
||||
- Multi-currency support needed
|
||||
- Legal or regulatory requirements vary by region
|
||||
|
||||
**Skip if:**
|
||||
- Backend doesn't support multiple countries or regions
|
||||
- All prices in one currency
|
||||
- No regional differences in catalog or pricing
|
||||
|
||||
## UI Patterns
|
||||
|
||||
### Placement Options
|
||||
|
||||
**Footer placement (modern and minimal):**
|
||||
- Bottom of page in footer
|
||||
- Less prominent but always accessible
|
||||
- Icon (flag or globe) + country code/name
|
||||
|
||||
**Header placement (most common):**
|
||||
- Top-right of navigation bar
|
||||
- Icon (flag or globe) + country code/name
|
||||
- Click opens dropdown or modal selector
|
||||
|
||||
**Modal/popup on first visit:**
|
||||
- Detect location and suggest country
|
||||
- Allow user to confirm or change
|
||||
- Store preference for future visits
|
||||
|
||||
### Selector Design Patterns
|
||||
|
||||
**Pattern 1: Dropdown (Recommended)**
|
||||
|
||||
Small, compact selector in header. Shows current country flag/name, click to open dropdown with country list.
|
||||
|
||||
**Pros:** Doesn't interrupt browsing, always accessible, familiar pattern.
|
||||
|
||||
**Pattern 2: Modal on First Visit**
|
||||
|
||||
Full-screen or centered modal on first visit. "Select your country to see accurate prices and shipping."
|
||||
|
||||
**Pros:** Forces initial selection, ensures accurate pricing from start.
|
||||
**Cons:** Can be intrusive, delays browsing.
|
||||
|
||||
**Tradeoff:** Modal ensures selection but adds friction. Dropdown is less intrusive but users may miss it.
|
||||
|
||||
**Pattern 3: Inline Banner**
|
||||
|
||||
Sticky banner at top: "Shipping to United States? Change" with link to selector.
|
||||
|
||||
**Pros:** Non-intrusive reminder, doesn't block content.
|
||||
**Cons:** Takes vertical space, easy to ignore.
|
||||
|
||||
### Country List Display
|
||||
|
||||
**Search + list:**
|
||||
- Search input at top
|
||||
- Alphabetical country list below
|
||||
- Popular countries at top (US, UK, Canada, etc.)
|
||||
- Flag icons for visual recognition
|
||||
|
||||
**Grouped by region:**
|
||||
- North America, Europe, Asia, etc.
|
||||
- Collapsible sections
|
||||
- Helpful for large lists (100+ countries)
|
||||
|
||||
**Format:**
|
||||
```
|
||||
🇺🇸 United States (USD)
|
||||
🇬🇧 United Kingdom (GBP)
|
||||
🇨🇦 Canada (CAD)
|
||||
───────────────────
|
||||
🇩🇪 Germany (EUR)
|
||||
🇫🇷 France (EUR)
|
||||
```
|
||||
|
||||
Show flag, country name, and currency code for clarity.
|
||||
|
||||
## State Management
|
||||
|
||||
### Storing Country Selection
|
||||
|
||||
**Client-side storage (recommended):**
|
||||
- localStorage or cookies
|
||||
- Persists across sessions
|
||||
- Key: `region_id` or `country_code`
|
||||
|
||||
**Why local storage:**
|
||||
- Fast access without API call
|
||||
- Available immediately on page load
|
||||
- No server round-trip needed
|
||||
|
||||
### Context Provider Pattern
|
||||
|
||||
**Recommended: Create context for region/country data.**
|
||||
|
||||
Provides quick access throughout the app to:
|
||||
- Selected country
|
||||
- Selected region (if applicable)
|
||||
- Currency
|
||||
- Available payment methods
|
||||
- Shipping options
|
||||
|
||||
**Benefits:**
|
||||
- Centralized country/region logic
|
||||
- Easy access from any component
|
||||
- Single source of truth
|
||||
- Simplified cart and product queries
|
||||
|
||||
**Example structure:**
|
||||
```typescript
|
||||
interface RegionContext {
|
||||
country: string
|
||||
region?: string
|
||||
currency: string
|
||||
changeCountry: (country: string) => void
|
||||
}
|
||||
```
|
||||
|
||||
### When to Apply Selection
|
||||
|
||||
**Apply country/region to:**
|
||||
- Product price display (convert currency, apply regional pricing)
|
||||
- Cart creation (set region for accurate totals)
|
||||
- Product queries (retrieve accurate pricing)
|
||||
- Checkout flow (shipping methods, payment options)
|
||||
- Content display (language, measurements)
|
||||
|
||||
## Backend Integration
|
||||
|
||||
### General Backend Requirements
|
||||
|
||||
**What backend needs to provide:**
|
||||
- List of available countries/regions
|
||||
- Mapping of countries to regions (if using regional structure)
|
||||
- Pricing per region or country
|
||||
- Product availability by region
|
||||
- Shipping methods by region
|
||||
- Supported payment methods by region
|
||||
|
||||
**API considerations:**
|
||||
- Fetch country/region list on app load
|
||||
- Pass selected country/region to product queries
|
||||
- Include region in cart creation
|
||||
- Validate country selection on backend
|
||||
|
||||
### Medusa Backend Integration
|
||||
|
||||
**For Medusa users, regions are critical for accurate pricing.**
|
||||
|
||||
Medusa uses regions (not individual countries) for pricing. A region can contain multiple countries.
|
||||
|
||||
**Key concepts:**
|
||||
- **Region**: Group of countries with shared pricing (e.g., "Europe" region)
|
||||
- **Country**: Individual country within a region
|
||||
- **Currency**: Each region has one currency
|
||||
|
||||
**Mapping country to region:**
|
||||
1. Customer selects country (e.g., "Germany")
|
||||
2. Find which region contains that country (e.g., "Europe" region)
|
||||
3. Store region ID for cart and product operations
|
||||
4. Use region for all pricing queries
|
||||
|
||||
**Required for:**
|
||||
- Creating carts: Must pass region ID
|
||||
- Retrieving products: Pass region to get accurate prices
|
||||
- Product availability: Products may be region-specific
|
||||
|
||||
**Implementation pattern:**
|
||||
Create a context that stores both country and region. When country changes, look up corresponding region and update both.
|
||||
|
||||
**For detailed Medusa region implementation, see:**
|
||||
- Medusa storefront regions documentation: https://docs.medusajs.com/resources/storefront-development/regions/context
|
||||
- Medusa JS SDK regions endpoints
|
||||
- Consult Medusa MCP server for real-time API details
|
||||
|
||||
**Other backends:**
|
||||
Check the ecommerce backend's documentation for country/region handling patterns.
|
||||
|
||||
## Detection and Defaults
|
||||
|
||||
### Auto-Detection
|
||||
|
||||
**IP-based geolocation (recommended):**
|
||||
Detect user's country from IP address. Use as default but allow user to change.
|
||||
|
||||
**Implementation:**
|
||||
- Use geolocation API or service (MaxMind, ipapi.co, CloudFlare)
|
||||
- Server-side detection (more accurate)
|
||||
- Set as default, show confirmation: "Shipping to United States?"
|
||||
|
||||
**Benefits:** Reduces friction, most users keep detected country.
|
||||
|
||||
**Tradeoff:** Not 100% accurate (VPNs, proxies). Always allow manual override.
|
||||
|
||||
### Fallback Strategy
|
||||
|
||||
**If detection fails or unavailable:**
|
||||
1. Check localStorage for previous selection
|
||||
2. Use browser language as hint (`navigator.language`)
|
||||
3. Default to primary market (e.g., US for US-based store)
|
||||
4. Prompt user to select on first interaction (cart, checkout)
|
||||
|
||||
**Never block browsing if country unknown.**
|
||||
Allow browsing with default pricing, prompt selection before checkout.
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Selector placement:**
|
||||
Mobile hamburger menu or bottom of page. Top-right in mobile header if space allows.
|
||||
|
||||
**Modal selector:**
|
||||
Full-screen modal on mobile for country selection. Large touch targets (48px), search input at top, easy scrolling.
|
||||
|
||||
**Sticky reminder:**
|
||||
Small banner: "Shipping to US? Change" with tap to open selector.
|
||||
|
||||
**Detection prompt:**
|
||||
Bottom sheet: "We detected you're in Germany. Is this correct?" with Confirm/Change buttons.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Country selector visible (header, footer, or first-visit modal)
|
||||
- [ ] Current country clearly displayed (flag, name, currency)
|
||||
- [ ] Dropdown or modal with country list
|
||||
- [ ] Search functionality for long country lists
|
||||
- [ ] Popular countries at top of list
|
||||
- [ ] Flag icons for visual recognition
|
||||
- [ ] Show currency code per country
|
||||
- [ ] localStorage persistence (save selection)
|
||||
- [ ] Context provider for region/country data
|
||||
- [ ] Auto-detection based on IP (optional)
|
||||
- [ ] Manual override always available
|
||||
- [ ] Apply to product prices (currency, regional pricing)
|
||||
- [ ] Apply to cart creation (set region)
|
||||
- [ ] Apply to checkout (shipping, payment methods)
|
||||
- [ ] Fallback if detection fails
|
||||
- [ ] Mobile: Full-screen modal or bottom sheet
|
||||
- [ ] Mobile: Large touch targets (48px)
|
||||
- [ ] Backend integration (fetch regions, map countries)
|
||||
- [ ] For Medusa: Region context with country-to-region mapping
|
||||
- [ ] For Medusa: Pass region to cart and product queries
|
||||
- [ ] ARIA label on selector button
|
||||
- [ ] Keyboard accessible (Tab, Enter, arrows)
|
||||
- [ ] Screen reader announces country changes
|
||||
|
||||
**Optional enhancements:**
|
||||
|
||||
- [ ] Currency conversion display (show original + converted)
|
||||
- [ ] Language selector tied to country
|
||||
- [ ] Shipping estimate based on country
|
||||
- [ ] Tax estimation display
|
||||
- [ ] Regional content (images, messaging)
|
||||
- [ ] "Not shipping to your country?" alternative
|
||||
@@ -0,0 +1,112 @@
|
||||
# Footer Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Essential Footer Elements](#essential-footer-elements)
|
||||
- [Dynamic Category Links (Ecommerce-Specific)](#dynamic-category-links-ecommerce-specific)
|
||||
- [Newsletter Signup](#newsletter-signup)
|
||||
- [Payment and Trust Badges](#payment-and-trust-badges)
|
||||
- [Mobile Footer](#mobile-footer)
|
||||
|
||||
## Overview
|
||||
|
||||
Footer provides supplementary navigation, company info, and trust signals. Appears on every page.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build multi-column layouts and navigation lists. This guide focuses on ecommerce footer patterns.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Navigation links (categories, pages)
|
||||
- Dynamic category fetching from backend
|
||||
- Legal links (Privacy, Terms)
|
||||
- Newsletter signup
|
||||
- Payment method badges
|
||||
- Social media links
|
||||
- Responsive (multi-column desktop, single-column mobile)
|
||||
|
||||
## Essential Footer Elements
|
||||
|
||||
### Must-Have Content
|
||||
|
||||
**Required:**
|
||||
- Navigation links (categories from backend)
|
||||
- Contact information (email, phone)
|
||||
- Legal links (Privacy Policy, Terms of Service)
|
||||
- Copyright notice with current year
|
||||
|
||||
**Strongly recommended:**
|
||||
- Newsletter signup form
|
||||
- Payment method badges
|
||||
- Social media links
|
||||
- Trust signals
|
||||
|
||||
### Multi-Column Layout (Desktop)
|
||||
|
||||
**Standard pattern: 4-5 columns**
|
||||
- Column 1: Shop/Categories (dynamic from backend)
|
||||
- Column 2: Customer Service (Contact, FAQ, Shipping)
|
||||
- Column 3: Company (About, Careers)
|
||||
- Column 4: Newsletter signup
|
||||
- Bottom: Legal links, payment badges, copyright
|
||||
|
||||
## Dynamic Category Links (Ecommerce-Specific)
|
||||
|
||||
**CRITICAL: Fetch categories from backend dynamically** - never hardcode. Fetch from ecommerce backend API (for Medusa: `sdk.store.category.list()`).
|
||||
|
||||
**Benefits:**
|
||||
- Stays in sync with main navigation
|
||||
- Categories added/removed automatically
|
||||
- No manual footer updates
|
||||
|
||||
**Guidelines:**
|
||||
- Show top-level categories only (5-8 max)
|
||||
- Match labels from main navigation
|
||||
- Cache category data (rarely changes)
|
||||
|
||||
## Newsletter Signup
|
||||
|
||||
**Essential elements:**
|
||||
- Email input + submit button ("Subscribe")
|
||||
- **Value proposition (CRITICAL)**: State clear benefit ("Get 10% off your first order", "Exclusive deals + early access"). Don't just say "Subscribe to newsletter".
|
||||
- Privacy note: "We respect your privacy" + link to privacy policy
|
||||
|
||||
**Layout:** Input + button inline (desktop), stacked (mobile). Full width on mobile.
|
||||
|
||||
## Payment and Trust Badges
|
||||
|
||||
**Payment method icons:**
|
||||
Display accepted payments (Visa, Mastercard, PayPal, Apple Pay, Google Pay). 40-50px icons, horizontal row, bottom of footer.
|
||||
|
||||
**Trust badges (optional):**
|
||||
Max 3-4 legitimate certifications (SSL, BBB, money-back guarantee). Only use real badges with verification links.
|
||||
|
||||
## Mobile Footer
|
||||
|
||||
**Single column, stacked:** Logo → Navigation → Newsletter → Social → Legal/copyright.
|
||||
|
||||
**Collapsible sections (optional):** Accordion pattern for navigation to reduce height. Keep newsletter/social always visible.
|
||||
|
||||
**Touch-friendly:** 44px minimum links, 8-12px spacing, 14-16px text, 48px newsletter input height.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Navigation links (categories, pages)
|
||||
- [ ] Categories fetched dynamically from backend
|
||||
- [ ] Contact information (email, phone)
|
||||
- [ ] Legal links (Privacy Policy, Terms of Service)
|
||||
- [ ] Copyright notice with current year
|
||||
- [ ] Newsletter signup form with value proposition
|
||||
- [ ] Payment method icons
|
||||
- [ ] Social media links
|
||||
- [ ] Responsive (4-5 columns desktop, single-column mobile)
|
||||
- [ ] Mobile: 44px touch targets
|
||||
- [ ] Mobile: Collapsible sections (optional)
|
||||
- [ ] Semantic HTML (`<footer>`, `<nav>` sections)
|
||||
- [ ] ARIA labels on navigation ("Footer navigation")
|
||||
- [ ] Keyboard accessible
|
||||
- [ ] Visible focus indicators
|
||||
- [ ] Color contrast 4.5:1 minimum
|
||||
- [ ] Consistent across all pages
|
||||
@@ -0,0 +1,241 @@
|
||||
# Hero Section Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Hero Types and When to Use](#hero-types-and-when-to-use)
|
||||
- [Content Guidelines](#content-guidelines)
|
||||
- [Multiple Heroes (Carousel)](#multiple-heroes-carousel)
|
||||
- [Mobile Hero](#mobile-hero)
|
||||
- [Performance](#performance)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Hero section is the prominent banner at top of homepage, immediately below navigation. First content users see - sets tone for shopping experience.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build full-width banners with images and text overlays. This focuses on ecommerce hero patterns.
|
||||
|
||||
**Key requirements:**
|
||||
- Above the fold (immediately visible)
|
||||
- Clear value proposition or promotional message
|
||||
- High-quality imagery
|
||||
- Strong call-to-action
|
||||
- Fast loading (critical for first impression)
|
||||
|
||||
## Hero Types and When to Use
|
||||
|
||||
### 1. Full-Width Banner (Most Common)
|
||||
|
||||
**Characteristics:**
|
||||
- Spans entire viewport width
|
||||
- Large background image or video
|
||||
- Text overlay with headline + CTA
|
||||
- Single focused message
|
||||
|
||||
**Best for:**
|
||||
- Seasonal campaigns ("Summer Sale")
|
||||
- New product arrivals
|
||||
- Brand storytelling
|
||||
- Single promotional focus
|
||||
- Simple, bold message
|
||||
|
||||
**Example:** Background image of products, headline "40% Off Summer Sale", CTA "Shop Now"
|
||||
|
||||
### 2. Split Hero (Image + Content)
|
||||
|
||||
**Characteristics:**
|
||||
- 50/50 or 60/40 split layout
|
||||
- Image on one side, text content on other
|
||||
- No text overlay on image
|
||||
- Cleaner, easier to read
|
||||
|
||||
**Best for:**
|
||||
- Product launches (show product clearly)
|
||||
- Detailed messaging (more text space)
|
||||
- Accessibility (no text-on-image contrast issues)
|
||||
- Professional/B2B stores
|
||||
|
||||
**Example:** Product image (left 50%), headline + benefits + CTA (right 50%)
|
||||
|
||||
### 3. Minimal Hero
|
||||
|
||||
**Characteristics:**
|
||||
- Large image, minimal text
|
||||
- Image does storytelling
|
||||
- Subtle headline, small CTA
|
||||
- Emphasis on visual brand
|
||||
|
||||
**Best for:**
|
||||
- Luxury brands (sophisticated aesthetic)
|
||||
- Lifestyle brands (aspirational imagery)
|
||||
- Photography-focused products
|
||||
- Brand over promotion
|
||||
|
||||
### 4. Video Hero
|
||||
|
||||
**Characteristics:**
|
||||
- Background video (muted, looping)
|
||||
- Text overlay on video
|
||||
- Fallback image for slow connections
|
||||
|
||||
**Best for:**
|
||||
- Fashion brands (show products in motion)
|
||||
- Lifestyle products (demonstrate usage)
|
||||
- High-budget campaigns
|
||||
- Brand storytelling with motion
|
||||
|
||||
**Important:** Auto-play muted, provide play/pause controls, optimize file size (<5MB), use poster image fallback.
|
||||
|
||||
### 5. Product Showcase Hero
|
||||
|
||||
**Characteristics:**
|
||||
- Multiple featured products in hero
|
||||
- Grid of 2-4 products
|
||||
- Quick links to product pages
|
||||
- Less promotional, more discovery
|
||||
|
||||
**Best for:**
|
||||
- Multi-category stores
|
||||
- Product-focused (not campaign-focused)
|
||||
- Quick product discovery
|
||||
- Minimal marketing, maximum browsing
|
||||
|
||||
## Content Guidelines
|
||||
|
||||
**Headline best practices:**
|
||||
- Short and impactful (5-10 words)
|
||||
- Clear value proposition ("Free Shipping on All Orders")
|
||||
- Urgency if time-sensitive ("48-Hour Flash Sale")
|
||||
- Benefit-focused ("Upgrade Your Style")
|
||||
- Avoid generic ("Welcome to Our Store")
|
||||
|
||||
**Subtext (optional):**
|
||||
- 10-20 words maximum
|
||||
- Expand on headline benefit
|
||||
- Add context or details
|
||||
- Not always necessary (clean design)
|
||||
|
||||
**Call-to-action:**
|
||||
- Single primary CTA button
|
||||
- Action-oriented text ("Shop Now", "Explore Category", "Get Started")
|
||||
- High contrast (stands out on image)
|
||||
- Large enough (48px height minimum)
|
||||
- Link to relevant landing page (sale, category, product listing)
|
||||
|
||||
**Image selection:**
|
||||
- High quality, professional photography
|
||||
- Shows products or lifestyle context
|
||||
- Represents brand aesthetic
|
||||
- Optimized for web (<500KB)
|
||||
- Responsive (different crops for mobile)
|
||||
- Ensure text overlay is readable (adequate contrast)
|
||||
|
||||
## Multiple Heroes (Carousel)
|
||||
|
||||
**Carousel pattern:**
|
||||
- 2-4 slides rotating automatically
|
||||
- Each slide = independent hero (own message, image, CTA)
|
||||
- Auto-rotate every 5-7 seconds (slow enough to read)
|
||||
- Manual controls (prev/next arrows, dot indicators)
|
||||
- Pause on hover (accessibility)
|
||||
|
||||
**When to use carousel:**
|
||||
- Multiple concurrent campaigns (Winter Sale + New Arrivals)
|
||||
- Different audience segments (Men/Women/Kids)
|
||||
- Seasonal variety showcase
|
||||
- Limited above-fold space
|
||||
|
||||
**When NOT to use carousel:**
|
||||
- Single focused campaign (just use one hero)
|
||||
- Users rarely see slides beyond first (carousel blindness)
|
||||
- Slower page load (multiple images)
|
||||
- Accessibility concerns (auto-rotating content)
|
||||
|
||||
**Carousel best practices:**
|
||||
- Max 3-4 slides (more = ignored)
|
||||
- First slide most important (most viewed)
|
||||
- Consistent layout across slides
|
||||
- Clear indicators showing progress
|
||||
- Don't rely on later slides for critical info
|
||||
- Pause on interaction (hover, focus)
|
||||
|
||||
## Mobile Hero
|
||||
|
||||
**Mobile adjustments (CRITICAL):**
|
||||
|
||||
**Layout:**
|
||||
- Full-width, portrait aspect (2:3 or 3:4)
|
||||
- Vertical composition (text overlays center/bottom)
|
||||
- Larger text for readability
|
||||
- Simplified message (shorter headline)
|
||||
|
||||
**Split hero on mobile:**
|
||||
- Stack vertically (image top, text bottom)
|
||||
- Don't use side-by-side (too cramped)
|
||||
|
||||
**Performance:**
|
||||
- Smaller images (<300KB)
|
||||
- Different image crop for mobile portrait
|
||||
- Use `srcset` or `<picture>` for responsive images
|
||||
- Consider static image instead of video (mobile data)
|
||||
|
||||
**Touch interactions:**
|
||||
- Large CTA button (48px height minimum)
|
||||
- Easy carousel controls (if used)
|
||||
- Swipe gesture for carousel slides
|
||||
|
||||
## Performance
|
||||
|
||||
**Critical for first impression:**
|
||||
|
||||
**Image optimization:**
|
||||
- WebP format with JPEG fallback
|
||||
- Lazy load below-fold content (not hero - it's above fold)
|
||||
- Responsive images (mobile gets smaller size)
|
||||
- Target: <500KB desktop, <300KB mobile
|
||||
- Use CDN for faster delivery
|
||||
|
||||
**Video optimization:**
|
||||
- <5MB file size maximum
|
||||
- Muted, autoplay, loop
|
||||
- Poster image (shows before video loads)
|
||||
- Fallback to image on slow connections
|
||||
- Consider not using on mobile (data/performance)
|
||||
|
||||
**LCP optimization:**
|
||||
- Hero image is often Largest Contentful Paint
|
||||
- Preload hero image: `<link rel="preload" as="image" href="hero.jpg">`
|
||||
- Inline critical CSS for hero
|
||||
- Avoid layout shift (set image dimensions)
|
||||
|
||||
**Target metrics:**
|
||||
- LCP < 2.5 seconds
|
||||
- No layout shift (CLS < 0.1)
|
||||
- Fast interaction (hero CTA clickable immediately)
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Above the fold (immediately visible)
|
||||
- [ ] Clear headline (5-10 words, value proposition)
|
||||
- [ ] High-quality image (professional, on-brand)
|
||||
- [ ] Primary CTA button (action-oriented, high contrast)
|
||||
- [ ] Fast loading (<500KB image desktop, <300KB mobile)
|
||||
- [ ] Responsive images (different sizes/crops for devices)
|
||||
- [ ] Mobile: Portrait aspect ratio (2:3 or 3:4)
|
||||
- [ ] Mobile: Vertical text placement (center/bottom)
|
||||
- [ ] Mobile: Large CTA (48px height minimum)
|
||||
- [ ] Text overlay readable (adequate contrast, background overlay)
|
||||
- [ ] If carousel: Max 3-4 slides
|
||||
- [ ] If carousel: Auto-rotate 5-7 seconds
|
||||
- [ ] If carousel: Pause on hover/focus
|
||||
- [ ] If carousel: Manual controls (arrows, dots)
|
||||
- [ ] If video: Muted, autoplay, loop
|
||||
- [ ] If video: Poster image fallback
|
||||
- [ ] If video: <5MB file size
|
||||
- [ ] Preload hero image (LCP optimization)
|
||||
- [ ] No layout shift (set image dimensions)
|
||||
- [ ] ARIA labels on carousel controls
|
||||
- [ ] Keyboard accessible (Tab to CTA, arrow keys for carousel)
|
||||
@@ -0,0 +1,239 @@
|
||||
# Megamenu Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [When to Use Megamenu](#when-to-use-megamenu)
|
||||
- [Content Organization](#content-organization)
|
||||
- [Layout Patterns](#layout-patterns)
|
||||
- [Trigger Behavior](#trigger-behavior)
|
||||
- [Mobile Alternative](#mobile-alternative)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Megamenu is a large, full-width dropdown navigation showing multiple columns of categories, links, and promotional content. Opens from navbar trigger items (e.g., "Shop", "Men", "Women").
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build dropdown menus with hover/click triggers. This focuses on ecommerce megamenu patterns.
|
||||
|
||||
**Key requirements:**
|
||||
- Full-width display (spans viewport)
|
||||
- Multiple columns for categories
|
||||
- Positioned directly below navbar
|
||||
- Optional promotional images
|
||||
- Mobile alternative (hamburger menu, not megamenu)
|
||||
|
||||
## When to Use Megamenu
|
||||
|
||||
**Use megamenu when:**
|
||||
- Large product catalog (10+ top-level categories)
|
||||
- Deep hierarchy (parent → child → grandchild levels)
|
||||
- Want to showcase featured products/campaigns
|
||||
- Multiple segments (Men, Women, Kids, etc.)
|
||||
- Visual storytelling needed
|
||||
|
||||
**Use simple dropdown when:**
|
||||
- Small catalog (<10 categories)
|
||||
- Flat category structure (1-2 levels)
|
||||
- Text-only navigation sufficient
|
||||
- Minimalist design preference
|
||||
|
||||
**Common megamenu triggers:**
|
||||
- "Shop" (all categories)
|
||||
- "Men", "Women", "Kids" (segmented)
|
||||
- "New Arrivals" (curated)
|
||||
- "Sale" (promotional)
|
||||
|
||||
## Content Organization
|
||||
|
||||
**Backend Integration (CRITICAL):**
|
||||
|
||||
Fetch categories dynamically from ecommerce backend - never hardcode categories. Categories change frequently (new products, seasonal updates, inventory changes). Fetch from API on component mount or during SSR.
|
||||
|
||||
**Column structure (3-5 columns recommended):**
|
||||
|
||||
**Column 1-3: Category columns**
|
||||
- Parent category header (bold, non-clickable or clickable to "View All")
|
||||
- Child categories below (clickable links)
|
||||
- 5-10 links per column maximum
|
||||
- Group related subcategories
|
||||
|
||||
**Example:**
|
||||
|
||||
```plaintext
|
||||
Electronics (header)
|
||||
Laptops
|
||||
Desktops
|
||||
Monitors
|
||||
Accessories
|
||||
View All Electronics
|
||||
```
|
||||
|
||||
**Column 4-5: Promotional/Featured**
|
||||
- Product image card (1-2 featured products)
|
||||
- Campaign banner ("Summer Sale", "New Arrivals")
|
||||
- "Shop the Look" curated sets
|
||||
- Seasonal promotions
|
||||
|
||||
**Content limits:**
|
||||
|
||||
- Max 5 columns (avoid overcrowding)
|
||||
- Max 10 links per column
|
||||
- 1-2 promotional images maximum
|
||||
- Keep height reasonable (<600px)
|
||||
|
||||
## Layout Patterns
|
||||
|
||||
### ⚠️ CRITICAL: Megamenu Positioning (Common Mistake)
|
||||
|
||||
**Common positioning errors that MUST be avoided:**
|
||||
|
||||
❌ **Mistake 1: Navbar doesn't have `position: relative`**
|
||||
- Without positioning context on navbar, megamenu won't position correctly
|
||||
- Megamenu will position relative to document body instead of navbar
|
||||
|
||||
❌ **Mistake 2: Megamenu positioned relative to trigger button**
|
||||
- Causes megamenu to appear offset, not aligned to left edge
|
||||
- Megamenu won't span full width of navbar
|
||||
- Different trigger positions cause inconsistent megamenu placement
|
||||
|
||||
❌ **Mistake 3: Megamenu doesn't span full width**
|
||||
- Using `width: auto` or no width constraint
|
||||
- Missing `left: 0` and `right: 0` properties
|
||||
- Results in narrow dropdown instead of full-width panel
|
||||
|
||||
---
|
||||
|
||||
**REQUIRED positioning pattern:**
|
||||
|
||||
**Visual structure:**
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ NAVBAR (position: relative) │
|
||||
│ [Logo] [Shop ▼] [Men] [Women] [Cart] │
|
||||
└─────────────────────────────────────────────────┘
|
||||
┌───────────────────────────────────────────────┐
|
||||
│ MEGAMENU (absolute, left: 0, full width) │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ Container (centered content) │ │
|
||||
│ │ [Col1] [Col2] [Col3] [Promo] │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
└───────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Required structure:**
|
||||
|
||||
1. **Navbar container**
|
||||
- MUST have `position: relative`
|
||||
- Creates positioning context for megamenu
|
||||
- Contains both trigger button and megamenu dropdown
|
||||
|
||||
2. **Megamenu dropdown**
|
||||
- MUST have `position: absolute`
|
||||
- MUST have `left: 0` (aligns to left edge of navbar)
|
||||
- MUST have `right: 0` OR `width: 100%` (spans full navbar width)
|
||||
- MUST have `top: 100%` (positioned directly below navbar)
|
||||
- Should have appropriate `z-index` (above content, below modals)
|
||||
|
||||
3. **Content wrapper (inside megamenu)**
|
||||
- Use constrained width container (e.g., `max-width`, `container`)
|
||||
- Center content with `margin: 0 auto`
|
||||
- Contains grid/columns for megamenu content
|
||||
|
||||
**Why this pattern is mandatory:**
|
||||
- Navbar `position: relative` creates positioning context
|
||||
- Megamenu `absolute` + `left: 0` + full width ensures consistent, full-width layout
|
||||
- Positioning relative to navbar (not trigger) prevents offset issues
|
||||
- Inner container centers content while maintaining full-width background
|
||||
|
||||
---
|
||||
|
||||
### Other Layout Considerations
|
||||
|
||||
- Positioned below navbar (no gap)
|
||||
- White/light background, boxed padding
|
||||
- Shadow or border for depth
|
||||
- High z-index (above page content, below modals)
|
||||
|
||||
**Column layout:**
|
||||
- Equal-width columns or flexible grid
|
||||
- Adequate spacing (24-32px between columns)
|
||||
- Left-aligned text in category columns
|
||||
- Right column(s) for promotional content
|
||||
- Responsive: Stack columns on tablet if needed
|
||||
|
||||
**Promotional images:**
|
||||
- Right-aligned (1-2 columns)
|
||||
- Aspect ratio: 2:3 or square
|
||||
- Product images or lifestyle photography
|
||||
- Clickable to product/category page
|
||||
- Include caption or CTA ("Shop Now")
|
||||
|
||||
## Trigger Behavior
|
||||
|
||||
**Desktop hover (recommended):**
|
||||
- Megamenu opens on trigger hover
|
||||
- **CRITICAL: Megamenu MUST stay open while hovering over the dropdown content**
|
||||
- Stays open while hovering trigger OR dropdown area
|
||||
- Closes only when mouse leaves both trigger and dropdown areas
|
||||
- Debounce close (200-300ms delay) to prevent accidental closure
|
||||
- Smooth fade-in/out transition (200-300ms)
|
||||
|
||||
**Why this is critical:**
|
||||
- If dropdown closes when moving from trigger to content, users can't access links
|
||||
- Frustrating UX - users can't interact with megamenu items
|
||||
- Common mistake: Only listening for hover on trigger, not on dropdown
|
||||
|
||||
**Desktop click (alternative):**
|
||||
- Click trigger to toggle open/close
|
||||
- Click outside to close
|
||||
- Better for touch-enabled laptops
|
||||
- Less accidental openings
|
||||
|
||||
**Hover flickering prevention:**
|
||||
- No gap between navbar and dropdown
|
||||
- Dropdown should slightly overlap navbar
|
||||
- Debounce close delay prevents flickering
|
||||
|
||||
## Mobile Alternative
|
||||
|
||||
**Do NOT use megamenu on mobile:**
|
||||
- Too large for mobile screens
|
||||
- Hard to navigate multi-column layout
|
||||
- Poor touch experience
|
||||
|
||||
**Mobile alternative (hamburger menu):**
|
||||
- Hamburger icon opens slide-in drawer
|
||||
- Vertical accordion for categories
|
||||
- Parent category expands to show children
|
||||
- Simple, scrollable list
|
||||
- See navbar.md for mobile navigation patterns
|
||||
|
||||
**Breakpoint:**
|
||||
- Megamenu: Desktop only (>1024px)
|
||||
- Hamburger: Tablet and mobile (<1024px)
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
- [ ] Triggered from navbar items ("Shop", segments)
|
||||
- [ ] **CRITICAL: Navbar container has `position: relative` (creates positioning context)**
|
||||
- [ ] **CRITICAL: Megamenu has `position: absolute` with `left: 0` (NOT positioned relative to trigger button)**
|
||||
- [ ] **CRITICAL: Megamenu spans full width (`right: 0` or `w-full`, NOT just `w-auto`)**
|
||||
- [ ] **CRITICAL: Megamenu positioned at `top: 100%` or `top-full` (directly below navbar)**
|
||||
- [ ] Full-width dropdown below navbar, spans entire navbar width
|
||||
- [ ] 3-5 columns for organization
|
||||
- [ ] Category hierarchy (parent → children links)
|
||||
- [ ] Optional promotional images (1-2)
|
||||
- [ ] **CRITICAL: Megamenu stays open when hovering over dropdown content (not just trigger)**
|
||||
- [ ] Hover trigger with debounced close (200-300ms)
|
||||
- [ ] Smooth fade-in/out transition
|
||||
- [ ] No flickering (no gap between navbar and dropdown)
|
||||
- [ ] Mobile: Use hamburger menu, NOT megamenu
|
||||
- [ ] Keyboard accessible (Tab through links, Escape closes)
|
||||
- [ ] `role="navigation"` on dropdown panel
|
||||
- [ ] ARIA labels on trigger buttons
|
||||
- [ ] Screen reader friendly (announce expand/collapse)
|
||||
- [ ] Max 10 links per column
|
||||
- [ ] Max 5 columns total
|
||||
- [ ] Fetched dynamically from backend (don't hardcode categories)
|
||||
@@ -0,0 +1,397 @@
|
||||
# Navbar Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Decision: Simple Dropdown vs Megamenu](#decision-simple-dropdown-vs-megamenu)
|
||||
- [Key Ecommerce Patterns](#key-ecommerce-patterns)
|
||||
- [Layout Structure](#layout-structure)
|
||||
- [Accessibility Essentials](#accessibility-essentials)
|
||||
- [Common Ecommerce Mistakes](#common-ecommerce-mistakes)
|
||||
- [Backend Integration](#backend-integration)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Primary navigation for ecommerce storefronts. Desktop: horizontal menu with category links. Mobile: hamburger drawer with accordion subcategories.
|
||||
|
||||
### ⚠️ CRITICAL: NEVER Hardcode Categories
|
||||
|
||||
**ALWAYS fetch categories dynamically from the backend. NEVER hardcode static category arrays.**
|
||||
|
||||
❌ **WRONG - DO NOT DO THIS:**
|
||||
```typescript
|
||||
// WRONG - Static hardcoded categories
|
||||
const categories = [
|
||||
{ name: "Women", href: "/categories/women" },
|
||||
{ name: "Men", href: "/categories/men" },
|
||||
{ name: "Accessories", href: "/categories/accessories" }
|
||||
]
|
||||
```
|
||||
|
||||
✅ **CORRECT - Fetch from backend:**
|
||||
```typescript
|
||||
// CORRECT - Fetch categories dynamically
|
||||
const [categories, setCategories] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
fetch(`${apiUrl}/store/product-categories`)
|
||||
.then(res => res.json())
|
||||
.then(data => setCategories(data.product_categories))
|
||||
}, [])
|
||||
```
|
||||
|
||||
**Why this matters:**
|
||||
- Categories change frequently (new categories, renamed, reordered)
|
||||
- Hardcoded categories become outdated immediately
|
||||
- Requires code changes every time categories change
|
||||
- Cannot scale to stores with dynamic catalogs
|
||||
- Defeats the purpose of headless commerce
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Desktop: Horizontal category links, cart/account/search right-aligned
|
||||
- Mobile: Hamburger drawer, cart stays visible in header (not hidden in drawer)
|
||||
- **CRITICAL: Fetch categories from backend dynamically (NEVER hardcode static arrays)**
|
||||
- Sticky: Recommended for easy cart access while browsing
|
||||
- Real-time updates: Cart count, login state, category changes
|
||||
|
||||
## Decision: Simple Dropdown vs Megamenu
|
||||
|
||||
**Use Simple Dropdown when:**
|
||||
- <10 top-level categories
|
||||
- Flat or shallow hierarchy (1-2 levels deep)
|
||||
- Minimal subcategories per parent
|
||||
- Focused/specialized product catalog
|
||||
|
||||
**Use Megamenu when:**
|
||||
- 10+ top-level categories
|
||||
- Deep hierarchy (3+ levels)
|
||||
- Need to showcase featured products in navigation
|
||||
- Complex product catalog
|
||||
- Fashion, electronics, or large inventory
|
||||
|
||||
**Mobile**: Always use drawer with accordion pattern, never megamenu on mobile.
|
||||
|
||||
See [megamenu.md](megamenu.md) for megamenu implementation details.
|
||||
|
||||
## Key Ecommerce Patterns
|
||||
|
||||
### Cart Indicator (CRITICAL)
|
||||
|
||||
**Always visible on both desktop and mobile:**
|
||||
- Desktop: Top-right, cart icon + count badge
|
||||
- Mobile: Top-right in header (NOT hidden in hamburger drawer)
|
||||
- This is non-negotiable - users expect cart always accessible
|
||||
|
||||
**Badge display:**
|
||||
- Shows item count (NOT price - confusing when variants change)
|
||||
- Only visible when cart has items (count > 0)
|
||||
- Show actual count up to 99, then "99+"
|
||||
- Position: Top-right corner of cart icon
|
||||
- ARIA label: `aria-label="Shopping cart with 3 items"`
|
||||
|
||||
**Real-time updates:**
|
||||
- Update count immediately when items added (optimistic UI)
|
||||
- No page refresh required
|
||||
- Sync with backend cart state
|
||||
- Handle errors gracefully (restore count if add fails)
|
||||
|
||||
**Click behavior:**
|
||||
- Option 1: Navigate to cart page
|
||||
- Option 2: Open cart popup/drawer (see cart-popup.md)
|
||||
- Choice depends on store type (see cart-popup.md for decision criteria)
|
||||
|
||||
✅ **CORRECT:**
|
||||
- Cart icon visible in mobile header
|
||||
- Badge shows count (not price)
|
||||
- Updates in real-time without page refresh
|
||||
- 44x44px touch target
|
||||
- Links to cart or opens cart popup
|
||||
|
||||
❌ **WRONG:**
|
||||
- Hiding cart in mobile hamburger drawer (users can't find it)
|
||||
- Showing price in badge (€25.99) instead of count
|
||||
- Cart count doesn't update until page refresh
|
||||
- No visual feedback when items added
|
||||
|
||||
### Category Navigation
|
||||
|
||||
**CRITICAL: Fetch dynamically from backend (NEVER hardcode):**
|
||||
|
||||
❌ **WRONG - These are all incorrect approaches:**
|
||||
```typescript
|
||||
// WRONG - Hardcoded array
|
||||
const categories = ["Women", "Men", "Kids", "Accessories"]
|
||||
|
||||
// WRONG - Static object array
|
||||
const categories = [
|
||||
{ id: 1, name: "Women", slug: "women" },
|
||||
{ id: 2, name: "Men", slug: "men" }
|
||||
]
|
||||
|
||||
// WRONG - Importing static data
|
||||
import { categories } from "./categories.ts"
|
||||
```
|
||||
|
||||
✅ **CORRECT - Fetch from backend API:**
|
||||
- Medusa: Use SDK category list method (verify exact method with docs/MCP)
|
||||
- Other backends: Call categories endpoint (check API documentation)
|
||||
- Fetch on component mount or during server-side rendering
|
||||
|
||||
**Why dynamic fetching is mandatory:**
|
||||
- Store owners add/remove/rename categories frequently
|
||||
- Category order and hierarchy changes
|
||||
- Multi-language stores need translated category names
|
||||
- Featured categories rotate (seasonal, promotions)
|
||||
- Hardcoded values require developer intervention for simple changes
|
||||
|
||||
**Caching strategy:**
|
||||
- Cache categories (revalidate on interval or manual trigger)
|
||||
- Use SWR, TanStack Query, or framework-level caching
|
||||
- Revalidate every 5-10 minutes or on page navigation
|
||||
- Update immediately when backend categories change
|
||||
|
||||
**Organization:**
|
||||
- 4-7 top-level categories ideal (max 10 on desktop)
|
||||
- Order comes from backend (respects admin's ordering)
|
||||
- Keep "Sale" or "New Arrivals" prominent if backend provides it
|
||||
- Maximum 2 levels in simple dropdown (category → subcategory)
|
||||
- Deeper hierarchies: Use megamenu or separate category pages
|
||||
|
||||
**Desktop behavior:**
|
||||
- Horizontal links with hover dropdowns for subcategories
|
||||
- Slight hover delay to prevent accidental triggers
|
||||
- Click parent to navigate to category page
|
||||
- Click child to navigate to subcategory
|
||||
|
||||
**Mobile behavior:**
|
||||
- All categories in hamburger drawer
|
||||
- Accordion pattern for subcategories (expand/collapse)
|
||||
- Close drawer on category click (except expanding accordion)
|
||||
- Scrollable drawer if categories exceed viewport height
|
||||
|
||||
✅ **CORRECT:**
|
||||
- Categories fetched from backend API on mount
|
||||
- Cache with revalidation strategy
|
||||
- Respects backend ordering and hierarchy
|
||||
- 4-7 top-level items on desktop (based on what backend returns)
|
||||
- Accordion for mobile subcategories
|
||||
- Consistent ordering across devices
|
||||
|
||||
❌ **WRONG:**
|
||||
- Hardcoded category array in component (NEVER DO THIS)
|
||||
- Static categories imported from file (NEVER DO THIS)
|
||||
- No cache invalidation (stale categories)
|
||||
- Too many top-level items (>10, overwhelming)
|
||||
- Different category order on desktop vs mobile
|
||||
- Categories don't update when backend changes
|
||||
|
||||
### User Account Indicator
|
||||
|
||||
**Two states based on authentication:**
|
||||
|
||||
**Logged out:**
|
||||
- Desktop: "Sign In" or "Log In" text + user icon
|
||||
- Mobile: User icon only
|
||||
- Click navigates to login page
|
||||
- Clear call-to-action
|
||||
|
||||
**Logged in:**
|
||||
- Desktop: User name, initials, or email + dropdown
|
||||
- Mobile: User name/initials or icon → account page
|
||||
- Dropdown menu (desktop): My Account, Orders, Wishlist, Sign Out
|
||||
- Fetch current user from backend authentication state
|
||||
|
||||
**Authentication state management:**
|
||||
- Check auth state from backend (not just localStorage)
|
||||
- Update immediately on login/logout events
|
||||
- Handle session expiration gracefully
|
||||
- Sync across tabs if possible
|
||||
|
||||
✅ **CORRECT:**
|
||||
- Shows "Sign In" when logged out
|
||||
- Shows user identifier when logged in
|
||||
- Dropdown with account actions
|
||||
- Checks backend auth state (not just client state)
|
||||
|
||||
❌ **WRONG:**
|
||||
- No indication of login state
|
||||
- Relies solely on localStorage (can be stale)
|
||||
- No dropdown for account actions when logged in
|
||||
- Missing logout option
|
||||
|
||||
### Mobile Navigation Pattern
|
||||
|
||||
**Hamburger drawer:**
|
||||
- Trigger: Hamburger icon (top-left)
|
||||
- Drawer: Slides from left, 80-85% width, full height, scrollable
|
||||
- Backdrop: Semi-transparent overlay, click to close
|
||||
- Content: All categories with accordion subcategories
|
||||
|
||||
**CRITICAL: Keep cart in header:**
|
||||
- Cart icon stays in mobile header (top-right)
|
||||
- Don't hide cart inside drawer
|
||||
- Users expect cart always accessible
|
||||
- Same for search icon if using icon-only search
|
||||
|
||||
**Account in drawer:**
|
||||
- Logged out: "Sign In" link in drawer header or top of menu
|
||||
- Logged in: User name/initials in drawer header with link to account
|
||||
|
||||
**Close behavior:**
|
||||
- Close button (X) in drawer header
|
||||
- Click backdrop overlay
|
||||
- Navigate to category (drawer closes)
|
||||
- Escape key
|
||||
|
||||
✅ **CORRECT:**
|
||||
- Cart stays in mobile header (visible)
|
||||
- Hamburger opens drawer from left
|
||||
- Backdrop overlay dims background
|
||||
- Close on navigation or backdrop click
|
||||
- Scrollable drawer for long menus
|
||||
|
||||
❌ **WRONG:**
|
||||
- Cart hidden inside hamburger drawer (cardinal sin)
|
||||
- Full-screen drawer (no backdrop)
|
||||
- Drawer doesn't close on navigation
|
||||
- Not scrollable (categories cut off)
|
||||
|
||||
### Bottom Navigation (Alternative for Mobile)
|
||||
|
||||
**When to use:**
|
||||
- Store has 3-5 key sections (Home, Browse, Cart, Account, Search)
|
||||
- App-like experience desired
|
||||
- Frequent switching between sections
|
||||
- Not suitable for complex category hierarchies
|
||||
|
||||
**Pattern:**
|
||||
- Fixed bar at bottom of screen (mobile only)
|
||||
- Icon + label for each section
|
||||
- Highlight active section
|
||||
- 5 items maximum
|
||||
- Direct navigation, no dropdowns
|
||||
|
||||
## Layout Structure
|
||||
|
||||
**Desktop:**
|
||||
- Left: Logo → Homepage
|
||||
- Center: Category links (horizontal)
|
||||
- Right: Search, Account, Cart
|
||||
|
||||
**Mobile:**
|
||||
- Left: Hamburger
|
||||
- Center: Logo
|
||||
- Right: Cart (+ Search icon optional)
|
||||
|
||||
**Sticky recommended:**
|
||||
- Keeps cart/account accessible while scrolling
|
||||
- Use `position: sticky` or `position: fixed`
|
||||
- Solid background color (hide scrolling content)
|
||||
- Adequate z-index to stay above content
|
||||
|
||||
## Accessibility Essentials
|
||||
|
||||
**Ecommerce-specific ARIA:**
|
||||
- Cart count: `aria-live="polite"` to announce changes (e.g., "3 items in cart")
|
||||
- Mobile drawer: `role="dialog"`, `aria-modal="true"`
|
||||
- Hamburger button: `aria-label="Open navigation menu"`, `aria-expanded="false"`
|
||||
- Active page: `aria-current="page"` on current category link
|
||||
- Dropdown indicators: `aria-expanded`, `aria-controls` for megamenu relationships
|
||||
|
||||
**Keyboard navigation:**
|
||||
- Tab through all links/buttons
|
||||
- Enter/Space to activate
|
||||
- Escape to close mobile menu or dropdowns
|
||||
- Visible focus indicators (outline/ring)
|
||||
|
||||
**Generic accessibility applies:**
|
||||
- Semantic HTML (`<header>`, `<nav>`)
|
||||
- Icon buttons need ARIA labels
|
||||
- 4.5:1 color contrast minimum
|
||||
- 44x44px touch targets on mobile
|
||||
|
||||
## Common Ecommerce Mistakes
|
||||
|
||||
❌ **CRITICAL: Hardcoded static categories** - NEVER create static category arrays like `const categories = ["Women", "Men"]` or import from static files. ALWAYS fetch from backend API. Categories change constantly - new categories added, names changed, ordering updated. Hardcoded categories require developer intervention for simple changes and defeat the purpose of dynamic commerce platforms. This is the #1 most common mistake.
|
||||
|
||||
❌ **Hiding cart in mobile drawer** - Users expect cart always visible. Keep cart icon in header (top-right), not hidden inside hamburger menu.
|
||||
|
||||
❌ **No real-time cart updates** - Update count immediately when items added (optimistic UI). Don't require page refresh.
|
||||
|
||||
❌ **Showing price in cart badge** - Show item count (number), not total price. Price display confuses when variants have different quantities.
|
||||
|
||||
❌ **No cache invalidation** - Categories become stale when backend changes. Revalidate periodically (5-10 min) or on manual trigger.
|
||||
|
||||
❌ **Hover-only dropdowns on mobile** - Use click/tap interactions. Hover doesn't work on touch devices.
|
||||
|
||||
❌ **Desktop navigation on mobile** - Use hamburger drawer pattern, not horizontal menu that doesn't fit.
|
||||
|
||||
❌ **Inconsistent category order** - Same order on desktop and mobile for consistency. Respect backend's category ordering.
|
||||
|
||||
## Backend Integration
|
||||
|
||||
### Category Fetching (CRITICAL - NEVER Hardcode)
|
||||
|
||||
**Implementation patterns:**
|
||||
|
||||
**Client-side fetching:**
|
||||
- Fetch categories in useEffect on mount
|
||||
- Store in state (use appropriate types for Medusa: StoreProductCategory)
|
||||
- Handle loading and error states
|
||||
- Map categories to navigation links
|
||||
- Use category.id as key, category.handle for URL, category.name for display
|
||||
|
||||
**With caching (RECOMMENDED):**
|
||||
- Use TanStack Query with queryKey ['categories']
|
||||
- Set staleTime: 5-10 minutes (categories rarely change)
|
||||
- Automatic loading/error states
|
||||
- Request deduplication if multiple components need categories
|
||||
|
||||
**Server-side fetching:**
|
||||
- Fetch in server component or load function
|
||||
- No loading state needed (rendered on server)
|
||||
- Better for SEO
|
||||
|
||||
**Cart state synchronization pattern:**
|
||||
- Subscribe to global cart state (Context)
|
||||
- Update navbar cart count when cart changes
|
||||
- Handle optimistic updates (show new count immediately on add to cart)
|
||||
- Sync with backend on events or interval
|
||||
|
||||
**Authentication state pattern:**
|
||||
- Check auth state from backend on mount
|
||||
- Listen for login/logout events
|
||||
- Update account indicator immediately
|
||||
- Handle session expiration gracefully
|
||||
|
||||
**Category update triggers:**
|
||||
- On page load/navigation
|
||||
- On manual refresh trigger
|
||||
- On revalidation interval (5-10 minutes)
|
||||
- After admin updates categories (webhook or polling)
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential navbar features:**
|
||||
|
||||
- [ ] **CRITICAL: Categories fetched dynamically from backend API (NOT hardcoded arrays)**
|
||||
- [ ] **CRITICAL: No static category imports or hardcoded category lists**
|
||||
- [ ] Desktop: Horizontal category links
|
||||
- [ ] Mobile: Hamburger drawer with accordion
|
||||
- [ ] Cart icon visible on both desktop and mobile header (NOT hidden in drawer)
|
||||
- [ ] Cart badge shows item count (not price)
|
||||
- [ ] Cart count updates in real-time
|
||||
- [ ] Categories use backend ordering (not manual ordering)
|
||||
- [ ] Account indicator shows login state
|
||||
- [ ] Logo links to homepage
|
||||
- [ ] 4-7 top-level categories displayed (max 10)
|
||||
- [ ] Mobile drawer closes on navigation
|
||||
- [ ] Sticky navigation (recommended)
|
||||
- [ ] 44x44px minimum touch targets
|
||||
- [ ] ARIA labels on icon buttons
|
||||
- [ ] `aria-live` on cart count for screen readers
|
||||
- [ ] Keyboard accessible with visible focus states
|
||||
- [ ] Categories cached with revalidation strategy (5-10 min)
|
||||
- [ ] Error handling for failed category fetch
|
||||
@@ -0,0 +1,221 @@
|
||||
# Popups Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [When to Use Popups](#when-to-use-popups)
|
||||
- [Ecommerce Popup Types](#ecommerce-popup-types)
|
||||
- [Timing and Triggers](#timing-and-triggers)
|
||||
- [Frequency Management](#frequency-management)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Popups (modals/overlays) appear over main content to capture attention for specific actions: newsletter signups, promotional offers, exit-intent offers.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build modals with close buttons and backdrop overlays. This focuses on ecommerce popup patterns.
|
||||
|
||||
**Critical balance**: Effective for conversions when used sparingly, intrusive and annoying when overused. Timing and frequency are critical for ecommerce.
|
||||
|
||||
## When to Use Popups
|
||||
|
||||
**Use popups when:**
|
||||
|
||||
- Offering significant value (10-20% first-purchase discount, free shipping)
|
||||
- Time-sensitive promotions (flash sale ending soon)
|
||||
- Exit-intent to recover abandoning visitors (last chance offer)
|
||||
- First-time visitor welcome (one-time only)
|
||||
- Important announcements (shipping delays, policy changes)
|
||||
|
||||
**Don't use popups for:**
|
||||
|
||||
- Every page visit (extremely annoying)
|
||||
- Multiple popups per session
|
||||
- Immediate page load (users haven't seen site yet)
|
||||
- Mobile users (especially full-screen takeovers - very disruptive)
|
||||
- Users who already signed up or dismissed
|
||||
|
||||
**Consider alternatives:**
|
||||
|
||||
- Top banner: Less intrusive, always visible, good for ongoing promotions
|
||||
- Inline forms: Homepage or footer newsletter signup, non-blocking
|
||||
- Slide-in (corner): From bottom-right, less disruptive than center popup
|
||||
- Post-purchase: Ask for email after successful order (high conversion)
|
||||
|
||||
**Popups are best when:** Need immediate attention, high-value offer justifies interruption, exit-intent (last chance).
|
||||
|
||||
## Ecommerce Popup Types
|
||||
|
||||
### 1. First-Purchase Discount
|
||||
|
||||
**Purpose**: Convert first-time visitors with discount incentive.
|
||||
|
||||
**Content:**
|
||||
- Headline: "Welcome! Get 10% Off Your First Order"
|
||||
- Email input
|
||||
- Discount code or automatic application
|
||||
- Subscribe button: "Get My Discount"
|
||||
|
||||
**Timing**: After 30-60 seconds on site OR after viewing 2-3 products (engagement signal).
|
||||
|
||||
**Frequency**: Once per user (cookie/localStorage). Don't show to returning customers.
|
||||
|
||||
### 2. Newsletter Signup
|
||||
|
||||
**Purpose**: Grow email list for marketing.
|
||||
|
||||
**Content:**
|
||||
- Value proposition: "Get exclusive deals and early access"
|
||||
- Email input
|
||||
- Subscribe button
|
||||
- Optional: First-purchase discount incentive (10-15% off)
|
||||
|
||||
**Timing**: After 50% scroll OR 60 seconds on site.
|
||||
|
||||
**Frequency**: Once per session. If dismissed, don't show for 30 days.
|
||||
|
||||
### 3. Exit-Intent Popup
|
||||
|
||||
**Purpose**: Recover abandoning visitors with last-chance offer.
|
||||
|
||||
**Trigger**: Mouse moves toward browser close/back button (desktop only).
|
||||
|
||||
**Content:**
|
||||
- Urgency: "Wait! Don't Miss Out"
|
||||
- Offer: "Take 10% Off Your Order" or "Free Shipping Today Only"
|
||||
- Email capture (optional): "Send me the code"
|
||||
- CTA: "Claim Offer" or "Continue Shopping"
|
||||
|
||||
**Best for**: Cart abandoners, product page exits, first-time visitors.
|
||||
|
||||
**Frequency**: Once per session. Don't show if user already added to cart or on checkout.
|
||||
|
||||
### 4. Cart Abandonment Reminder
|
||||
|
||||
**Purpose**: Remind user of items in cart before leaving.
|
||||
|
||||
**Trigger**: Exit-intent when cart has items but user navigating away.
|
||||
|
||||
**Content:**
|
||||
- "Your Cart is Waiting"
|
||||
- Show cart summary (items, total)
|
||||
- CTA: "Complete Your Order" or "View Cart"
|
||||
- Optional incentive: "Complete in 10 minutes for free shipping"
|
||||
|
||||
**Frequency**: Once per session with items in cart.
|
||||
|
||||
### 5. Promotional Announcement
|
||||
|
||||
**Purpose**: Announce sales, new arrivals, or site-wide events.
|
||||
|
||||
**Content:**
|
||||
- Headline: "Flash Sale: 40% Off Everything"
|
||||
- Subtext: "Ends in 3 hours"
|
||||
- CTA: "Shop Now"
|
||||
|
||||
**Timing**: Immediate on page load (if major event), OR after 30 seconds.
|
||||
|
||||
**Frequency**: Once per day during promotion period.
|
||||
|
||||
## Timing and Triggers
|
||||
|
||||
**Time-based:**
|
||||
- 30-60 seconds after page load (enough time to browse)
|
||||
- Never immediate (0 seconds) - users need to see site first
|
||||
|
||||
**Engagement-based:**
|
||||
- After 50% scroll (shows interest)
|
||||
- After viewing 2-3 products (qualified visitor)
|
||||
- After adding to cart (exit-intent only)
|
||||
|
||||
**Exit-intent:**
|
||||
- Mouse moves toward close/back button (desktop)
|
||||
- Scroll-up toward address bar (mobile - less reliable)
|
||||
- Only trigger once per session
|
||||
- Don't trigger on checkout pages (interrupts purchase)
|
||||
|
||||
**Page-specific:**
|
||||
- Homepage: Welcome/discount popup
|
||||
- Product pages: Exit-intent with product-specific offer
|
||||
- Cart page: Don't use popups (already engaged)
|
||||
- Checkout: Never use popups (critical flow)
|
||||
|
||||
## Frequency Management
|
||||
|
||||
**Critical for UX**: Don't show same popup repeatedly to same user.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
1. **Cookie/localStorage tracking**: Store dismissal/signup with timestamp
|
||||
2. **Respect dismissals**: If user closes popup, don't show for 30 days
|
||||
3. **Signed-up users**: Never show newsletter popup again
|
||||
4. **Session limits**: Max 1 popup per session
|
||||
5. **Time cooldown**: If dismissed, wait 30 days before showing again
|
||||
|
||||
**Example tracking:**
|
||||
```javascript
|
||||
// On popup dismiss
|
||||
localStorage.setItem('popup_dismissed', Date.now())
|
||||
localStorage.setItem('popup_type', 'welcome_discount')
|
||||
|
||||
// Before showing popup
|
||||
const dismissedTime = localStorage.getItem('popup_dismissed')
|
||||
const daysSince = (Date.now() - dismissedTime) / (1000 * 60 * 60 * 24)
|
||||
if (daysSince < 30) {
|
||||
// Don't show popup
|
||||
}
|
||||
```
|
||||
|
||||
**Progressive disclosure:**
|
||||
- Session 1: Welcome discount popup
|
||||
- Session 2+: Exit-intent only (if applicable)
|
||||
- Never stack multiple popups
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Mobile popups are MORE intrusive:**
|
||||
- Smaller screen = popup takes more space
|
||||
- Harder to close (small X button)
|
||||
- Disrupts mobile browsing flow
|
||||
- Can hurt mobile SEO (Google penalty for intrusive interstitials)
|
||||
|
||||
**Mobile best practices:**
|
||||
|
||||
1. **Use sparingly**: Consider top banner or inline forms instead
|
||||
2. **Make easily dismissable**: Large close button (44x44px), tap outside to close
|
||||
3. **Delay longer**: 60+ seconds instead of 30 seconds
|
||||
4. **Smaller size**: 90% width max, not full-screen
|
||||
5. **Exit-intent**: Less reliable on mobile, avoid
|
||||
6. **Google penalty**: Avoid full-screen popups on mobile (hurts rankings)
|
||||
|
||||
**Mobile alternative**: Sticky bottom bar (less intrusive)
|
||||
- "Get 10% Off - Sign Up" with email input
|
||||
- Always visible but doesn't block content
|
||||
- Better mobile UX than popup
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Clear value proposition (discount, benefit)
|
||||
- [ ] Single focused CTA
|
||||
- [ ] Easy to close (X button, backdrop click, Escape key)
|
||||
- [ ] Delayed timing (30-60s, not immediate)
|
||||
- [ ] Frequency management (localStorage/cookie tracking)
|
||||
- [ ] Respect dismissals (30-day cooldown)
|
||||
- [ ] Never show to signed-up users
|
||||
- [ ] Max 1 popup per session
|
||||
- [ ] Exit-intent for cart abandoners (desktop only)
|
||||
- [ ] Don't show on checkout pages
|
||||
- [ ] Mobile: Use sparingly, consider alternatives
|
||||
- [ ] Mobile: Large close button (44x44px)
|
||||
- [ ] Mobile: Not full-screen (90% width max)
|
||||
- [ ] Email validation before submit
|
||||
- [ ] Loading state on submit
|
||||
- [ ] Success message or redirect
|
||||
- [ ] Keyboard accessible (Tab, Escape, Enter)
|
||||
- [ ] `role="dialog"` and `aria-modal="true"`
|
||||
- [ ] Focus trap (keep focus within popup)
|
||||
- [ ] ARIA label on close button
|
||||
- [ ] Screen reader announcements on open
|
||||
@@ -0,0 +1,125 @@
|
||||
# Product Card Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Price Display (Ecommerce-Specific)](#price-display-ecommerce-specific)
|
||||
- [Action Buttons and Variant Handling](#action-buttons-and-variant-handling)
|
||||
- [Badges and Labels](#badges-and-labels)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Ecommerce Checklist](#ecommerce-checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Product cards display products in grids (product listings, search results, related products). Key ecommerce considerations: clear pricing, quick add-to-cart, and stock indicators.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build cards with images, titles, and buttons. This guide focuses on ecommerce-specific patterns.
|
||||
|
||||
### Key Ecommerce Requirements
|
||||
|
||||
- Clear, prominent pricing (including sale prices)
|
||||
- Variant handling for add-to-cart
|
||||
- Stock status indicators
|
||||
- Sale/New/Out of Stock badges
|
||||
- Responsive grid (1 col mobile, 2-3 tablet, 3-4 desktop)
|
||||
- Fast image loading (lazy load, optimized)
|
||||
|
||||
## Price Display (Ecommerce-Specific)
|
||||
|
||||
### Regular vs Sale Pricing
|
||||
|
||||
**Sale price display:**
|
||||
- Sale price: Larger, bold, red or accent color
|
||||
- Original price: Smaller, struck through (~~$79.99~~), gray
|
||||
- Position sale price before original price
|
||||
- Optional: Show discount percentage badge (-20%)
|
||||
|
||||
**Format consistently:**
|
||||
- Always include currency symbol ($49.99)
|
||||
- Consistent decimals ($49.99 not $49.9 or $50)
|
||||
- For Medusa: Display prices as-is (no divide by 100)
|
||||
|
||||
### Price Range (Multiple Variants)
|
||||
|
||||
**When variants have different prices:**
|
||||
- Show "From $49" or "$49 - $79"
|
||||
- Makes it clear price varies by selection
|
||||
- Don't show range if all variants same price
|
||||
|
||||
## Action Buttons and Variant Handling
|
||||
|
||||
### Add to Cart with Variants (CRITICAL)
|
||||
|
||||
**Key challenge**: Products with variants require variant selection before adding to cart.
|
||||
|
||||
**Handling strategies:**
|
||||
|
||||
1. **Add first variant by default** - Click adds `product.variants[0]`. Fast for simple products (1-2 variants).
|
||||
2. **Redirect to product page** - Navigate to detail page for variant selection. Best for complex products (size + color + material).
|
||||
3. **Quick View modal** - Variant selector in modal. Good middle ground (desktop only).
|
||||
|
||||
**Decision:**
|
||||
- Simple products (1-2 variants): Add first variant
|
||||
- Fashion/apparel with sizes: Require size selection (redirect or Quick View)
|
||||
- Complex products (3+ variant types): Redirect to product page
|
||||
|
||||
**Button behavior:**
|
||||
- Loading state ("Adding..."), disable during loading
|
||||
- Optimistic UI update (cart count immediately)
|
||||
- Success feedback (toast, cart popup, or checkmark)
|
||||
- **Don't navigate away** (stay on listing page)
|
||||
- Handle errors (out of stock, API failure)
|
||||
|
||||
**Wishlist button (optional)**: Heart icon, top-right over image. Empty when not saved, filled (red) when saved. Refer to wishlist.md for more details.
|
||||
|
||||
## Badges and Labels
|
||||
|
||||
**Badge priority** (show max 1-2 per card):
|
||||
|
||||
1. **Out of Stock** (highest) - Gray/black overlay on image, disables add-to-cart
|
||||
2. **Sale/Discount** - "Sale" or "-20%", red/accent, top-left corner
|
||||
3. **New** - "New" for recent products, blue/green, top-left corner
|
||||
4. **Low Stock** (optional) - "Only 3 left", orange, creates urgency
|
||||
|
||||
**Display**: Top-left corner (except Out of Stock overlay), small but readable, high contrast.
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
### Grid Layout
|
||||
|
||||
**Mobile-specific adjustments:**
|
||||
- 2 columns maximum on mobile (never 3+)
|
||||
- Larger touch targets (44px minimum for buttons)
|
||||
- Always show "Add to Cart" button (no hover-only)
|
||||
- Simplified content (hide optional elements like brand)
|
||||
- Smaller images for performance (<400px wide)
|
||||
|
||||
### Touch Interactions
|
||||
|
||||
**No hover states on mobile:**
|
||||
- Don't hide actions behind hover
|
||||
- Always show primary button
|
||||
- Use tap states (active state) instead of hover
|
||||
|
||||
## Ecommerce Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Clear product image (optimized, lazy loaded)
|
||||
- [ ] Product title (truncated to 2 lines max)
|
||||
- [ ] Price prominently displayed
|
||||
- [ ] Sale price shown correctly (struck-through original price)
|
||||
- [ ] Currency symbol included
|
||||
- [ ] For Medusa: Price displayed as-is (not divided by 100)
|
||||
- [ ] Add to Cart button with loading state
|
||||
- [ ] Variant handling strategy (first variant, redirect, or Quick View)
|
||||
- [ ] Optimistic UI update (cart count immediately)
|
||||
- [ ] Success feedback (toast or cart popup)
|
||||
- [ ] Don't navigate away after adding to cart
|
||||
- [ ] Out of Stock badge (disables add-to-cart)
|
||||
- [ ] Sale badge when price reduced
|
||||
- [ ] Responsive grid (1 col mobile, 2-3 tablet, 3-4 desktop)
|
||||
- [ ] Touch-friendly on mobile (44px buttons)
|
||||
- [ ] Keyboard accessible (focus states, Enter to activate)
|
||||
- [ ] Descriptive alt text on images
|
||||
- [ ] Semantic HTML (`<article>` wrapper)
|
||||
@@ -0,0 +1,217 @@
|
||||
# Product Reviews Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Review Display Patterns](#review-display-patterns)
|
||||
- [Rating Summary and Distribution](#rating-summary-and-distribution)
|
||||
- [Sorting and Filtering](#sorting-and-filtering)
|
||||
- [Review Submission](#review-submission)
|
||||
- [Trust Signals](#trust-signals)
|
||||
- [SEO Integration](#seo-integration)
|
||||
|
||||
## Overview
|
||||
|
||||
Product reviews build trust and influence purchase decisions. Reviews with ratings convert 270% better than products without.
|
||||
|
||||
**Assumed knowledge**: Claude knows how to build forms and display lists. This guide focuses on ecommerce review patterns and trust signals.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Star rating summary (1-5 stars) with distribution
|
||||
- Individual reviews with ratings, text, author, date
|
||||
- Sorting (Most Recent, Most Helpful, Highest/Lowest Rating)
|
||||
- Filtering by rating (5 stars only, 4+ stars)
|
||||
- Verified purchase badges
|
||||
- Helpful votes (upvote system)
|
||||
- Review submission form
|
||||
- Mobile-optimized
|
||||
|
||||
## Review Display Patterns
|
||||
|
||||
### Placement
|
||||
|
||||
**On product page:**
|
||||
- Below product details (after add-to-cart)
|
||||
- Before related products
|
||||
- Anchor link in product info: "★★★★★ (127 reviews)"
|
||||
|
||||
**Separate reviews page:**
|
||||
- Only for very large catalogs (500+ reviews)
|
||||
- Link: "View All Reviews"
|
||||
- Most stores show reviews inline on product page
|
||||
|
||||
## Rating Summary and Distribution
|
||||
|
||||
### Average Rating Display
|
||||
|
||||
**Show prominently:**
|
||||
- Average rating: "★★★★★ 4.5 out of 5"
|
||||
- Total review count: "Based on 127 reviews"
|
||||
- Large stars (24-32px)
|
||||
|
||||
### Rating Distribution (CRITICAL)
|
||||
|
||||
**Visual breakdown with clickable bars:**
|
||||
```
|
||||
5 ★ [████████████████████] 82 (65%)
|
||||
4 ★ [██████░░░░░░░░░░░░░░] 25 (20%)
|
||||
3 ★ [██░░░░░░░░░░░░░░░░░░] 10 (8%)
|
||||
2 ★ [█░░░░░░░░░░░░░░░░░░░] 5 (4%)
|
||||
1 ★ [█░░░░░░░░░░░░░░░░░░░] 5 (3%)
|
||||
```
|
||||
|
||||
**Make bars clickable:**
|
||||
- Click to filter reviews by rating
|
||||
- Shows only selected star ratings
|
||||
- "Show all" to reset filter
|
||||
|
||||
**Why distribution matters:**
|
||||
- Perfect 5.0 rating seems fake (customers trust 4.2-4.5 average)
|
||||
- Showing negative reviews builds trust
|
||||
- Distribution helps customers understand product quality
|
||||
|
||||
### No Reviews State
|
||||
|
||||
**When no reviews:**
|
||||
- "No reviews yet"
|
||||
- "Be the first to review this product"
|
||||
- "Write a Review" button prominent
|
||||
- Don't show 0 stars or empty rating
|
||||
|
||||
## Sorting and Filtering
|
||||
|
||||
### Sort Options (CRITICAL)
|
||||
|
||||
**Essential sorting:**
|
||||
- **Most Recent** (default) - shows latest feedback
|
||||
- **Most Helpful** (by upvotes) - surfaces best reviews
|
||||
- **Highest Rating** (5 stars first) - see positive feedback
|
||||
- **Lowest Rating** (1 star first) - see concerns
|
||||
|
||||
**Dropdown selector:**
|
||||
```
|
||||
Sort by: [Most Recent ▾]
|
||||
```
|
||||
|
||||
### Filter Options
|
||||
|
||||
**Filter by rating:**
|
||||
- All ratings (default)
|
||||
- 5 stars only
|
||||
- 4+ stars
|
||||
- 3 stars or less (see negative feedback)
|
||||
|
||||
**Filter by criteria:**
|
||||
- Verified purchases only (highest trust)
|
||||
- With photos only (visual proof)
|
||||
- Recent (last 30 days, 6 months)
|
||||
|
||||
**Show filtered count:**
|
||||
- "Showing 24 of 127 reviews"
|
||||
|
||||
## Review Submission
|
||||
|
||||
### Review Form Fields
|
||||
|
||||
**Required:**
|
||||
- Star rating (1-5 stars selector)
|
||||
- Review text (textarea, 50-500 characters)
|
||||
- Reviewer name (if not logged in)
|
||||
|
||||
**Optional:**
|
||||
- Review title/headline
|
||||
- Upload images (2-5 max)
|
||||
- Would you recommend? (Yes/No)
|
||||
|
||||
**Form placement:**
|
||||
- "Write a Review" button opens modal or inline form
|
||||
- Position near rating summary
|
||||
|
||||
### Form Validation
|
||||
|
||||
**Requirements:**
|
||||
- Rating must be selected
|
||||
- Minimum review length (50 characters)
|
||||
- Show character counter: "50 / 500 characters"
|
||||
- Validate before submit
|
||||
|
||||
**Success:**
|
||||
- "Thank you for your review!"
|
||||
- "Your review is pending approval" (if moderation enabled)
|
||||
|
||||
## Trust Signals
|
||||
|
||||
### Verified Purchase Badge (CRITICAL)
|
||||
|
||||
**Display:**
|
||||
- Badge or checkmark: "✓ Verified Purchase"
|
||||
- Position near reviewer name
|
||||
- Green color or checkmark icon
|
||||
- Only for confirmed customers
|
||||
|
||||
**Why it matters:**
|
||||
- Builds trust (real customer, not fake)
|
||||
- Reduces suspicion of paid reviews
|
||||
- Higher credibility
|
||||
|
||||
### Helpful Votes
|
||||
|
||||
**Upvote/downvote system:**
|
||||
- "Was this review helpful?"
|
||||
- [👍 Yes (24)] [👎 No (2)]
|
||||
- Click to vote (one vote per user)
|
||||
- Powers "Most Helpful" sorting
|
||||
|
||||
**Benefits:**
|
||||
- Surfaces most useful reviews
|
||||
- Community validation
|
||||
- Reduces impact of unhelpful reviews
|
||||
|
||||
### Review Images (Optional)
|
||||
|
||||
Customer-uploaded photos (3-4 max per review, 60-80px thumbnails, click to enlarge). Visual proof increases trust and engagement.
|
||||
|
||||
### Store Responses (Recommended)
|
||||
|
||||
Seller replies below original review (indented, light gray background). Respond to negative reviews professionally - shows you care, addresses concerns without being defensive.
|
||||
|
||||
## SEO Integration
|
||||
|
||||
**AggregateRating Schema (CRITICAL):** Add structured data to show star ratings in search results. Include `ratingValue` (avg rating), `reviewCount`, `bestRating` (5), `worstRating` (1).
|
||||
|
||||
**SEO benefits:** Star ratings in search results, higher CTR, rich snippets. See seo.md for implementation details.
|
||||
|
||||
**Important:** Only include if reviews are real. Fake reviews violate Google guidelines.
|
||||
|
||||
## Display Patterns
|
||||
|
||||
**Individual review card:**
|
||||
Star rating (16-20px) + text + reviewer name (first name + initial) + date + verified badge + helpful votes. Truncate long reviews (200-300 chars) with "Read more".
|
||||
|
||||
**Mobile:**
|
||||
Single column, touch-friendly votes (44px), full-screen sort select, filter bottom sheet, "Load more" pagination.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Star rating summary (average + count)
|
||||
- [ ] Rating distribution bar chart (5 to 1 stars)
|
||||
- [ ] Clickable bars to filter by rating
|
||||
- [ ] Sort dropdown (Most Recent, Most Helpful, Highest/Lowest)
|
||||
- [ ] Filter options (verified, with photos, by rating)
|
||||
- [ ] Individual reviews with: stars, text, name, date
|
||||
- [ ] Verified purchase badge
|
||||
- [ ] Helpful votes (upvote/downvote)
|
||||
- [ ] Review submission form (rating, text)
|
||||
- [ ] Form validation (minimum length, required rating)
|
||||
- [ ] "Read more" for long reviews
|
||||
- [ ] Store responses to reviews (recommended)
|
||||
- [ ] Review images (customer uploads, optional)
|
||||
- [ ] Mobile: Touch targets 44px minimum
|
||||
- [ ] Pagination or "Load more" button
|
||||
- [ ] No reviews state ("Be the first to review")
|
||||
- [ ] AggregateRating structured data (SEO)
|
||||
- [ ] ARIA labels for star ratings
|
||||
- [ ] Keyboard accessible (all interactions)
|
||||
@@ -0,0 +1,174 @@
|
||||
# Product Slider Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [When to Use Product Sliders](#when-to-use-product-sliders)
|
||||
- [Slider Patterns](#slider-patterns)
|
||||
- [Product Display](#product-display)
|
||||
- [Navigation Controls](#navigation-controls)
|
||||
- [Mobile Sliders](#mobile-sliders)
|
||||
- [Performance](#performance)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Product slider (carousel) displays multiple products horizontally with navigation to scroll through them. Used for related products, recently viewed, bestsellers, and featured products.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build carousels with navigation. This focuses on ecommerce product slider patterns.
|
||||
|
||||
**Key requirements:**
|
||||
- Horizontal scrolling of product cards
|
||||
- Arrow navigation (prev/next)
|
||||
- Optional dot indicators
|
||||
- Mobile: Swipe gesture support
|
||||
- Responsive product count (4-6 visible desktop, 2-3 mobile)
|
||||
- Lazy loading for off-screen products
|
||||
|
||||
## When to Use Product Sliders
|
||||
|
||||
**Use for:**
|
||||
- Related products (product page)
|
||||
- Recently viewed (product page, homepage)
|
||||
- "You May Also Like" (product page)
|
||||
- Bestsellers / Featured products (homepage)
|
||||
- "Frequently Bought Together" (product page)
|
||||
- New arrivals (homepage)
|
||||
- Category showcases (homepage)
|
||||
|
||||
**Don't use for:**
|
||||
- Main product images (use gallery instead)
|
||||
- Critical content (not all users scroll/swipe)
|
||||
- Checkout flow (keep linear)
|
||||
- Primary navigation (use grid for discoverability)
|
||||
|
||||
## Slider Patterns
|
||||
|
||||
**Continuous scroll:**
|
||||
- Shows 4-6 products at once (desktop)
|
||||
- Scroll left/right by 1-2 products at a time
|
||||
- Smooth animated transition (300-400ms)
|
||||
- Most common pattern
|
||||
|
||||
**Infinite loop (optional):**
|
||||
- Wraps to beginning after end
|
||||
- Good for small product sets (<10 items)
|
||||
- Creates continuous browsing feel
|
||||
- Not necessary for large sets
|
||||
|
||||
**Snap to alignment:**
|
||||
- Products snap to grid after scroll
|
||||
- Prevents partial product visibility
|
||||
- Better visual alignment
|
||||
- Improves browsing experience
|
||||
|
||||
**Auto-play (NOT recommended for products):**
|
||||
- Automatic scrolling without user action
|
||||
- Poor UX for product sliders (users lose control)
|
||||
- Only use for promotional banners/hero images
|
||||
- If using: Pause on hover, slow speed (5-7s)
|
||||
|
||||
## Product Display
|
||||
|
||||
**Product cards in sliders:**
|
||||
- Same cards as product grids (see product-card.md)
|
||||
- Simplified on mobile (less detail, smaller images)
|
||||
- Image, title, price minimum
|
||||
- Optional: Rating, "Add to Cart" (desktop only)
|
||||
- Adequate spacing between cards (16-24px)
|
||||
|
||||
**Responsive display:**
|
||||
- Large desktop (>1440px): 5-6 products visible
|
||||
- Desktop (1024-1440px): 4-5 products
|
||||
- Tablet (768-1024px): 3-4 products
|
||||
- Mobile (<768px): 2 products (sometimes 1.5 for scroll hint)
|
||||
|
||||
**Scroll hint on mobile:**
|
||||
- Show 1.5 products (partial visibility of next)
|
||||
- Indicates more content to swipe
|
||||
- Improves discoverability
|
||||
- Better than showing exact 2 products
|
||||
|
||||
## Navigation Controls
|
||||
|
||||
**Arrow buttons:**
|
||||
- Left/right arrows outside slider
|
||||
- Desktop: Always visible or show on hover
|
||||
- Mobile: Hidden (swipe gesture preferred)
|
||||
- Position: Vertically centered
|
||||
- Size: 40-48px touch targets
|
||||
- Disable left arrow at start, right arrow at end (no infinite loop)
|
||||
|
||||
**Dot indicators (optional):**
|
||||
- Show progress through slider
|
||||
- Each dot = one "page" of products
|
||||
- Position: Below slider, centered
|
||||
- Small (8-12px dots)
|
||||
- Only if many products (>12)
|
||||
- Less common for product sliders (more for hero carousels)
|
||||
|
||||
**Keyboard navigation:**
|
||||
- Tab through visible product cards
|
||||
- Arrow keys scroll slider (optional)
|
||||
- Focus management on scroll
|
||||
|
||||
## Mobile Sliders
|
||||
|
||||
**Touch gestures:**
|
||||
- Horizontal swipe to scroll
|
||||
- Native scroll momentum
|
||||
- Snap to product alignment
|
||||
- No arrow buttons (swipe is intuitive)
|
||||
|
||||
**Mobile-specific adjustments:**
|
||||
- 2 products visible (or 1.5 for hint)
|
||||
- Larger touch targets on products
|
||||
- Remove hover-only features (Quick View)
|
||||
- Faster scroll animations (200-300ms)
|
||||
|
||||
**Performance on mobile:**
|
||||
- Lazy load off-screen products
|
||||
- Smaller image sizes
|
||||
- Limit initial products loaded (8-10)
|
||||
- Load more on scroll
|
||||
|
||||
## Performance
|
||||
|
||||
**Lazy loading (critical):**
|
||||
- Only load visible products initially
|
||||
- Load adjacent products (left/right) on demand
|
||||
- Significantly improves page load time
|
||||
- Use Intersection Observer API
|
||||
|
||||
**Image optimization:**
|
||||
- Responsive images (smaller for mobile)
|
||||
- WebP format with fallback
|
||||
- Lazy load off-screen images
|
||||
- Optimized thumbnails (<300KB)
|
||||
|
||||
**Limit slider length:**
|
||||
- Max 20-30 products per slider
|
||||
- "View All" link to full category page
|
||||
- Improves performance
|
||||
- Prevents endless scrolling
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
- [ ] 4-6 products visible (desktop), 2 (mobile)
|
||||
- [ ] Arrow navigation (desktop)
|
||||
- [ ] Swipe gesture (mobile)
|
||||
- [ ] Product cards with image, title, price
|
||||
- [ ] Responsive product count
|
||||
- [ ] Smooth scroll transitions (300-400ms)
|
||||
- [ ] Snap to product alignment
|
||||
- [ ] Lazy load off-screen products
|
||||
- [ ] "View All" link if many products (>20)
|
||||
- [ ] Disable arrows at start/end
|
||||
- [ ] Keyboard accessible (Tab through products)
|
||||
- [ ] Mobile: No arrows, swipe only
|
||||
- [ ] Optimized images (<300KB)
|
||||
- [ ] Spacing between products (16-24px)
|
||||
- [ ] ARIA labels on navigation (`aria-label="Previous products"`)
|
||||
- [ ] `role="region"` on slider container
|
||||
- [ ] NO auto-play for product sliders
|
||||
@@ -0,0 +1,101 @@
|
||||
# Search Component
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Search Placement](#search-placement)
|
||||
- [Autocomplete and Product Suggestions](#autocomplete-and-product-suggestions)
|
||||
- [Search Results Page](#search-results-page)
|
||||
- [Empty States](#empty-states)
|
||||
- [Recent and Popular Searches](#recent-and-popular-searches)
|
||||
- [Mobile Search](#mobile-search)
|
||||
|
||||
## Overview
|
||||
|
||||
Search is critical for ecommerce - users with search intent convert at higher rates. Provide fast, relevant product discovery with autocomplete.
|
||||
|
||||
**Assumed knowledge**: AI agents know how to build search inputs with icons and clear buttons. This guide focuses on ecommerce search patterns.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Prominent search input (always accessible)
|
||||
- Instant autocomplete after 2-3 characters
|
||||
- Product suggestions with images
|
||||
- Fast, relevant search results
|
||||
- Filters to refine results
|
||||
- Empty state guidance
|
||||
- Mobile full-screen search modal
|
||||
|
||||
## Search Placement
|
||||
|
||||
**Desktop**: Navbar center (between logo and cart) or right side. Always visible, 300-500px width. Part of sticky navbar. Never hide in hamburger menu.
|
||||
|
||||
**Mobile**: Magnifying glass icon in top-right (44x44px minimum). Opens full-screen modal - eliminates distractions, maximizes suggestion space, better typing experience.
|
||||
|
||||
## Autocomplete and Product Suggestions
|
||||
|
||||
**Show suggestions** after 2-3 characters (not 1). Debounce 300ms to prevent excessive API calls.
|
||||
|
||||
**Display 5-10 product suggestions:**
|
||||
- Small image (40-60px), title, price
|
||||
- Clickable to product page
|
||||
- Optional: Category/brand suggestions, popular terms
|
||||
- Divide sections with headers
|
||||
- "View all results for [query]" footer link
|
||||
|
||||
**Backend integration**: Fetch from search API. Check with ecommerce platform's documentation for API reference.
|
||||
|
||||
## Search Results Page
|
||||
|
||||
**Header**: "Search Results for '[query]'" + result count ("24 products found"). Search bar visible and pre-filled for refining.
|
||||
|
||||
**Grid layout**: Same as product listings (see product-listing.md). 1-4 columns based on device.
|
||||
|
||||
**Sorting**: Relevance (default, unique to search), Price Low/High, Newest.
|
||||
|
||||
**Filters**: Sidebar (desktop) or drawer (mobile). Category, Price, Brand, Availability with result counts.
|
||||
|
||||
## Empty States
|
||||
|
||||
**No results**: "No results for '[query]'" with helpful suggestions (check spelling, try broader keywords, browse categories). "Browse All Products" button + links to popular categories.
|
||||
|
||||
**Loading state**: Product card skeletons (6-8 cards), minimum 300ms display to avoid flashing.
|
||||
|
||||
## Recent and Popular Searches
|
||||
|
||||
**Recent searches** (user-specific, localStorage): Show 3-5 recent searches when input focused (before typing). Helps re-search without retyping.
|
||||
|
||||
**Popular searches** (site-wide, from backend): Show 5-10 trending terms when focused. Pill/tag styling.
|
||||
|
||||
Display both on: Empty input focus (desktop dropdown), mobile modal open.
|
||||
|
||||
## Mobile Search
|
||||
|
||||
**Full-screen modal pattern:**
|
||||
- Header: Back button (44x44px) + search input (48px height, auto-focus, `type="search"`)
|
||||
- Content: Recent/popular searches (empty), autocomplete (typing), scrollable
|
||||
- Close: Back button, device back gesture, Escape key
|
||||
|
||||
## Ecommerce Search Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Prominent search input in navbar (desktop)
|
||||
- [ ] Search icon clearly visible (mobile)
|
||||
- [ ] Full-screen modal on mobile tap
|
||||
- [ ] Autocomplete after 2-3 characters
|
||||
- [ ] Debounced API calls (300ms)
|
||||
- [ ] Product suggestions with images, prices
|
||||
- [ ] "View all results" link in dropdown
|
||||
- [ ] Search results page shows query
|
||||
- [ ] Result count displayed
|
||||
- [ ] Sort by Relevance (default for search)
|
||||
- [ ] Filters for refining results (category, price, brand)
|
||||
- [ ] Empty state with helpful guidance
|
||||
- [ ] Loading state indicator (skeleton)
|
||||
- [ ] Recent searches (localStorage)
|
||||
- [ ] Popular searches (from backend)
|
||||
- [ ] Mobile: Auto-focus, large input (48px)
|
||||
- [ ] Keyboard navigation (arrow keys, Enter, Escape)
|
||||
- [ ] ARIA labels (`role="search"`, `aria-label`)
|
||||
- [ ] Accessible to screen readers
|
||||
@@ -0,0 +1,391 @@
|
||||
# Connecting to Backend
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Detecting the Backend](#detecting-the-backend-critical)
|
||||
- [Framework Detection](#framework-detection)
|
||||
- [Environment Configuration](#environment-configuration)
|
||||
- [Backend-Specific Integration](#backend-specific-integration)
|
||||
- [Authentication Patterns](#authentication-patterns)
|
||||
- [Cart State Management](#cart-state-management)
|
||||
- [Error Handling for Ecommerce](#error-handling-for-ecommerce)
|
||||
- [Performance Patterns](#performance-patterns)
|
||||
- [Data Fetching with TanStack Query](#data-fetching-with-tanstack-query-recommended)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Best practices for connecting storefront to ecommerce backend APIs. Framework-agnostic patterns for authentication, cart state management, error handling, and performance optimization.
|
||||
|
||||
**For Medusa-specific integration**, see `reference/medusa.md` for SDK setup, pricing, regions, and Medusa patterns.
|
||||
|
||||
## Detecting the Backend (CRITICAL)
|
||||
|
||||
**Before implementing any backend integration, identify which ecommerce backend is being used.**
|
||||
|
||||
### Detection Strategy
|
||||
|
||||
**1. Check for monorepo structure:**
|
||||
```bash
|
||||
# Look for backend directory
|
||||
ls -la ../backend
|
||||
ls -la ./backend
|
||||
ls -la ../../apps/backend
|
||||
```
|
||||
|
||||
Common monorepo patterns:
|
||||
- `/apps/storefront` + `/apps/backend`
|
||||
- `/frontend` + `/backend`
|
||||
- `/packages/web` + `/packages/api`
|
||||
|
||||
**2. Check package.json dependencies:**
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@medusajs/js-sdk": "...", // Medusa
|
||||
// check other ecommerce frameworks...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**3. Check environment variables:**
|
||||
```bash
|
||||
# Look in .env, .env.local, .env.example
|
||||
grep -i "api\|backend\|medusa\|shopify\|commerce" .env*
|
||||
```
|
||||
|
||||
Common patterns:
|
||||
- `NEXT_PUBLIC_MEDUSA_BACKEND_URL` → Medusa
|
||||
- Custom `API_URL` or `BACKEND_URL` → Other backend
|
||||
|
||||
**4. If unsure, ASK THE USER:**
|
||||
|
||||
```markdown
|
||||
I need to connect to the ecommerce backend. Which backend are you using?
|
||||
|
||||
Options:
|
||||
- Medusa (open-source headless commerce)
|
||||
- Custom backend
|
||||
- Other
|
||||
```
|
||||
|
||||
### Backend Documentation and MCP Servers
|
||||
|
||||
**ALWAYS refer to the backend's official documentation or MCP server for:**
|
||||
|
||||
- API endpoints and data structures
|
||||
- Authentication requirements
|
||||
- SDK usage and installation
|
||||
- Environment configuration
|
||||
- Rate limits and best practices
|
||||
|
||||
**For Medusa:**
|
||||
- Documentation: https://docs.medusajs.com
|
||||
- MCP Server: If available, use Medusa MCP server for real-time API information
|
||||
- JS SDK docs: https://docs.medusajs.com/resources/js-sdk
|
||||
- See `reference/medusa.md` for detailed integration guide
|
||||
|
||||
**For other backends:**
|
||||
- Check the backend's documentation portal
|
||||
- Look for MCP server if available
|
||||
- Verify API endpoints and authentication methods
|
||||
- Never assume API structure without verification
|
||||
|
||||
**Important:** Do not guess API endpoints or data formats. Always verify with documentation or ask the user to confirm the backend's API structure.
|
||||
|
||||
## Framework Detection
|
||||
|
||||
Identify the frontend framework to determine appropriate data fetching patterns:
|
||||
|
||||
**Next.js:**
|
||||
- App Router: Server Components (async/await), Client Components (useEffect/TanStack Query)
|
||||
- Pages Router: getServerSideProps/getStaticProps (server), useEffect (client)
|
||||
|
||||
**SvelteKit:**
|
||||
- Load functions for server-side data
|
||||
- Client-side: fetch in component lifecycle
|
||||
|
||||
**TanStack Start:**
|
||||
- Server functions for server-side data
|
||||
- Client-side: fetch with React hooks
|
||||
|
||||
**General Rule:**
|
||||
- **Server-side for initial load**: SEO, performance, security (product pages, listings)
|
||||
- **Client-side for interactions**: Cart, filters, search, user-specific data
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
**Store API URLs and keys in environment variables:**
|
||||
|
||||
```typescript
|
||||
// .env.local
|
||||
NEXT_PUBLIC_API_URL=https://api.example.com
|
||||
NEXT_PUBLIC_PUBLISHABLE_KEY=pk_...
|
||||
```
|
||||
|
||||
**Framework-specific prefixes:**
|
||||
- Next.js: `NEXT_PUBLIC_` for client-side
|
||||
- SvelteKit: `PUBLIC_` for client-side
|
||||
- Vite-based (TanStack Start): `VITE_` for client-side
|
||||
|
||||
**Security:**
|
||||
- ❌ NEVER expose secret/admin keys in client-side code
|
||||
- ✅ Publishable keys are safe for client (Medusa, Stripe)
|
||||
- ✅ Secret keys only in server-side code or environment
|
||||
|
||||
## Backend-Specific Integration
|
||||
|
||||
### Medusa Backend
|
||||
|
||||
**For complete Medusa integration guide**, see `reference/medusa.md` which covers:
|
||||
- SDK installation and setup
|
||||
- Vite configuration (for TanStack Start, etc.)
|
||||
- TypeScript types from `@medusajs/types`
|
||||
- Price display (never divide by 100)
|
||||
- Common operations (products, cart, categories, customers)
|
||||
- Custom endpoints
|
||||
- Region state management
|
||||
- Error handling with SDK
|
||||
|
||||
### Other Backends
|
||||
|
||||
For non-Medusa backends (custom APIs, third-party platforms):
|
||||
|
||||
**1. Consult backend's API documentation** for:
|
||||
- Authentication requirements
|
||||
- Available endpoints
|
||||
- Request/response formats
|
||||
- SDK availability (check if official SDK exists)
|
||||
|
||||
**2. Use backend's official SDK if available** - provides type safety, error handling, and best practices
|
||||
|
||||
**3. If no SDK, create API client wrapper:**
|
||||
- Centralize API calls in one module
|
||||
- Group by resource (products, cart, customers, orders)
|
||||
- Handle authentication (include tokens/cookies)
|
||||
- Handle errors consistently
|
||||
- Use native fetch or axios
|
||||
|
||||
## Authentication Patterns
|
||||
|
||||
### Customer Authentication
|
||||
|
||||
**Session-based (cookies):**
|
||||
- Backend manages session via cookies
|
||||
- No manual token management needed
|
||||
- Works across page refreshes
|
||||
- Common in traditional ecommerce backends
|
||||
- Call backend login endpoint, check auth state, logout methods
|
||||
|
||||
**Token-based (JWT, OAuth):**
|
||||
- Store token in localStorage or secure cookie after login
|
||||
- Include token in Authorization header for all authenticated requests
|
||||
- Common in headless/API-first backends
|
||||
- Format: `Authorization: Bearer {token}`
|
||||
|
||||
### Protecting Customer Routes
|
||||
|
||||
**Check authentication before rendering customer-specific pages** (account, orders, addresses):
|
||||
|
||||
- **Server-side**: Check auth in server functions (getServerSideProps, load functions, etc.). Redirect to login if not authenticated.
|
||||
- **Client-side**: Check auth state on mount. Redirect to login if not authenticated.
|
||||
|
||||
Use framework-specific auth patterns for redirects.
|
||||
|
||||
### Cart Access Pattern
|
||||
|
||||
**Guest carts:**
|
||||
- Store cart ID in localStorage or cookie
|
||||
- Check for existing cart ID on app load
|
||||
- Create new cart if none exists
|
||||
- Allows shopping without account
|
||||
- Persists across sessions
|
||||
|
||||
**Logged-in carts:**
|
||||
- Associate cart with customer account
|
||||
- Syncs across devices
|
||||
- **CRITICAL: Merge guest cart with customer cart on login** - Transfer guest cart items to customer's account cart, then clear guest cart ID from localStorage
|
||||
|
||||
## Cart State Management
|
||||
|
||||
**Critical ecommerce pattern**: Cart must be accessible throughout the app.
|
||||
|
||||
### Global Cart State
|
||||
|
||||
**React Context (for simple cases):**
|
||||
- Create CartContext and CartProvider
|
||||
- Store cart state and cartId (from localStorage)
|
||||
- Load cart on mount if cartId exists
|
||||
- Provide methods: addItem, removeItem, updateQuantity, clearCart
|
||||
- Update cart state after each operation
|
||||
|
||||
**State management libraries (Zustand, Redux):**
|
||||
- Use for complex state requirements
|
||||
- Better for large applications
|
||||
- Easier to debug with DevTools
|
||||
- Same pattern: Store cart, provide actions, sync with backend
|
||||
|
||||
**Key requirements:**
|
||||
- Cart accessible from any component
|
||||
- Real-time cart count updates
|
||||
- Optimistic UI updates (update UI immediately, sync with backend)
|
||||
|
||||
### Cart Cleanup After Order Placement (CRITICAL)
|
||||
|
||||
**IMPORTANT: After order is successfully placed, you MUST reset the cart state.**
|
||||
|
||||
**Common issue:** Cart popup and global cart state still show old items after order completion. This happens when cart state isn't cleared after checkout.
|
||||
|
||||
**Required cleanup actions:**
|
||||
|
||||
1. **Clear cart from global state** - Reset cart state to null/empty in Context/Zustand/Redux
|
||||
2. **Clear localStorage cart ID** - Remove cart ID: `localStorage.removeItem('cart_id')`
|
||||
3. **Invalidate cart queries** - If using TanStack Query: `queryClient.invalidateQueries({ queryKey: ['cart'] })`
|
||||
4. **Update cart count to 0** - Navbar and UI should reflect empty cart
|
||||
|
||||
**When to clear:**
|
||||
- After successful order placement (order confirmed)
|
||||
- On navigation to order confirmation page
|
||||
- Before redirecting to thank you page
|
||||
|
||||
**Why this is critical:**
|
||||
- Prevents "phantom cart" from appearing in cart popup after order
|
||||
- Ensures clean state for next shopping session
|
||||
- Improves UX by not showing old cart items
|
||||
|
||||
## Error Handling for Ecommerce
|
||||
|
||||
### Ecommerce-Specific Errors
|
||||
|
||||
**Out of stock:**
|
||||
- Catch errors when adding to cart
|
||||
- Check for "out of stock" or "inventory" in error message
|
||||
- Show user-friendly message: "Sorry, this item is now out of stock"
|
||||
- Update product availability UI to show out of stock
|
||||
|
||||
**Price changed during checkout:**
|
||||
- Compare cart total with expected total
|
||||
- If different, show warning: "Prices have been updated. Please review your cart."
|
||||
- Highlight changed prices in cart
|
||||
|
||||
**Payment failed:**
|
||||
- Catch errors during order completion
|
||||
- Check for specific payment errors: payment_declined, insufficient_funds, etc.
|
||||
- Show specific messages:
|
||||
- Payment declined → "Payment declined. Please try a different payment method."
|
||||
- Insufficient funds → "Insufficient funds. Please use a different card."
|
||||
- Generic → "Payment failed. Please try again or contact support."
|
||||
|
||||
**Session expired:**
|
||||
- Catch 401/Unauthorized errors
|
||||
- Clear auth state
|
||||
- Redirect to login with message: "Your session has expired. Please log in again."
|
||||
|
||||
### User-Friendly Error Messages
|
||||
|
||||
**Transform technical errors to clear messages:**
|
||||
- Network/fetch errors → "Unable to connect. Please check your internet connection."
|
||||
- Timeout errors → "Request timed out. Please try again."
|
||||
- Inventory errors → "This item is no longer available in the requested quantity."
|
||||
- Generic fallback → "Something went wrong. Please try again or contact support."
|
||||
|
||||
**Pattern**: Check error message or status code, map to user-friendly message, show in UI (toast, banner, inline).
|
||||
|
||||
## Performance Patterns
|
||||
|
||||
### Data Fetching with TanStack Query (RECOMMENDED)
|
||||
|
||||
**Use TanStack Query for all backend API calls** - provides automatic caching, request deduplication, loading/error states, and optimistic updates.
|
||||
|
||||
**Installation:** `npm install @tanstack/react-query`
|
||||
|
||||
**Setup:**
|
||||
- Create QueryClient with default options (staleTime: 5 min, retry: 1)
|
||||
- Wrap app with QueryClientProvider
|
||||
|
||||
**Query pattern (for fetching data):**
|
||||
- Use `useQuery` with queryKey and queryFn
|
||||
- queryKey: Array with resource and identifier `['products', categoryId]`
|
||||
- queryFn: API call function
|
||||
- Returns: `data`, `isLoading`, `error`
|
||||
- Use for: Products, cart, customer data, categories
|
||||
|
||||
**Mutation pattern (for modifying data):**
|
||||
- Use `useMutation` with mutationFn
|
||||
- mutationFn: API operation (add to cart, update, delete)
|
||||
- onSuccess: Update cache or invalidate queries
|
||||
- Returns: `mutate` function, `isPending` state
|
||||
- Use for: Add to cart, remove from cart, update quantities, place order
|
||||
|
||||
**Benefits:**
|
||||
- Automatic caching (no manual cache management)
|
||||
- Built-in loading/error states
|
||||
- Request deduplication
|
||||
- Optimistic updates (update UI before server responds)
|
||||
- Cache invalidation strategies
|
||||
|
||||
**Ecommerce-specific usage:**
|
||||
- Products: Long stale time (5-10 min) - products don't change often
|
||||
- Cart: Short or no stale time - prices/inventory can change
|
||||
- Categories: Long stale time - rarely change
|
||||
|
||||
### Caching Strategy
|
||||
|
||||
**Client-side caching:**
|
||||
- TanStack Query handles automatically with `staleTime` and `cacheTime`
|
||||
- Configure globally or per-query
|
||||
- Product data: 5-10 min stale time
|
||||
- Cart data: Fresh on every fetch
|
||||
- Categories: Long stale time
|
||||
|
||||
**Server-side caching (framework-specific):**
|
||||
- Next.js: Use `revalidate` export or cache configuration
|
||||
- Set revalidation period (e.g., 300 seconds for product pages)
|
||||
- Static generation with ISR for product pages
|
||||
|
||||
### Request Deduplication
|
||||
|
||||
TanStack Query and modern frameworks handle this automatically - multiple components requesting same data result in single request.
|
||||
|
||||
### Pagination Pattern
|
||||
|
||||
**Offset-based:** Pass limit and offset parameters to API `limit: 24, offset: page * 24`
|
||||
|
||||
**Cursor-based (better performance):** Pass limit and cursor (last item ID) `limit: 24, cursor: lastProductId`
|
||||
|
||||
Check backend documentation for supported pagination type.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential backend integration:**
|
||||
|
||||
- [ ] Backend detected (Medusa, Shopify, custom, etc.)
|
||||
- [ ] Environment variables configured (API URL, keys)
|
||||
- [ ] Framework-specific data fetching patterns identified
|
||||
- [ ] **RECOMMENDED: TanStack Query installed and configured for API calls**
|
||||
- [ ] Server-side fetching for product pages (SEO)
|
||||
- [ ] Client-side fetching for cart and user interactions (use TanStack Query)
|
||||
- [ ] Authentication flow implemented (login/logout)
|
||||
- [ ] Cart ID persisted in localStorage or cookies
|
||||
- [ ] Global cart state management (context or store)
|
||||
- [ ] Cart count synced across app
|
||||
- [ ] Optimistic UI updates for cart operations
|
||||
- [ ] Error handling for out of stock scenarios
|
||||
- [ ] Error handling for payment failures
|
||||
- [ ] Session expiration handling (redirect to login)
|
||||
- [ ] User-friendly error messages (not technical)
|
||||
- [ ] Caching strategy for product data
|
||||
- [ ] Stock availability checks before checkout
|
||||
- [ ] Price change detection and warnings
|
||||
|
||||
**For Medusa backends, also check:**
|
||||
- [ ] Medusa SDK installed (`@medusajs/js-sdk` + `@medusajs/types`)
|
||||
- [ ] SDK initialized with baseUrl and publishableKey
|
||||
- [ ] Vite SSR config added (if using TanStack Start/Vite)
|
||||
- [ ] Using official types from `@medusajs/types`
|
||||
- [ ] Not dividing prices by 100 (display as-is)
|
||||
- [ ] Region context implemented for multi-region stores
|
||||
- [ ] Region passed to cart and product queries
|
||||
|
||||
See `reference/medusa.md` for complete Medusa integration guide.
|
||||
388
.agents/skills/storefront-best-practices/reference/design.md
Normal file
388
.agents/skills/storefront-best-practices/reference/design.md
Normal file
@@ -0,0 +1,388 @@
|
||||
# Design Guidelines
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Discovering Existing Brand Identity](#discovering-existing-brand-identity)
|
||||
- [Critical Consistency Rules](#critical-consistency-rules)
|
||||
- [When to Ask User Approval](#when-to-ask-user-approval)
|
||||
- [New Project Setup](#new-project-setup)
|
||||
- [Decision Tree](#decision-tree)
|
||||
- [Common Mistakes](#common-mistakes)
|
||||
|
||||
## Overview
|
||||
|
||||
**Purpose:** Provide guardrails to maintain brand consistency when building UI components. This prevents agents from accidentally introducing inconsistent colors, fonts, or design patterns.
|
||||
|
||||
**Critical principle:** ALWAYS discover and use existing design tokens before creating new components. NEVER introduce new colors or fonts without user approval.
|
||||
|
||||
**When to apply:** Before creating any UI component or design-related change.
|
||||
|
||||
## Discovering Existing Brand Identity
|
||||
|
||||
Before implementing any component, identify existing brand colors, typography, and design patterns. AI agents can do this - focus on WHAT to look for, not detailed HOW.
|
||||
|
||||
### What to Look For
|
||||
|
||||
**Colors:**
|
||||
1. **Tailwind config** (`tailwind.config.ts/js`) - Check `theme.extend.colors` or `theme.colors`
|
||||
2. **CSS variables** (globals.css, app.css) - Look for `:root { --color-primary: ... }`
|
||||
3. **Existing components** - Scan 2-3 components for color usage patterns
|
||||
|
||||
**Typography:**
|
||||
1. **Tailwind config** - Check `theme.extend.fontFamily`
|
||||
2. **Font imports** - Look in layout files or CSS (Next.js `next/font`, Google Fonts, local fonts)
|
||||
3. **CSS variables** - Check for `--font-sans`, `--font-heading`
|
||||
4. **Existing components** - Identify font usage patterns
|
||||
|
||||
**Other patterns:**
|
||||
- Spacing scale (p-4, mb-6, etc.)
|
||||
- Border radius (rounded-lg, rounded-xl)
|
||||
- Shadows (shadow-md, shadow-lg)
|
||||
- Interactive states (hover, focus colors)
|
||||
|
||||
### Detecting Tailwind Version (CRITICAL)
|
||||
|
||||
**ALWAYS check the Tailwind CSS version before writing utility classes.**
|
||||
|
||||
Tailwind v3 and v4 have different syntax, and mixing them causes errors.
|
||||
|
||||
**How to detect version:**
|
||||
1. **Check `package.json`**: Look for `"tailwindcss": "^3.x.x"` or `"tailwindcss": "^4.x.x"`
|
||||
2. **Check config file**:
|
||||
- v3: Uses `tailwind.config.js/ts` with `module.exports` or `export default`
|
||||
- v4: May use CSS-based config with `@import "tailwindcss"`
|
||||
3. **Check existing components**: Look at class usage patterns
|
||||
|
||||
**Key differences:**
|
||||
|
||||
**Tailwind v3:**
|
||||
```tsx
|
||||
// v3 syntax
|
||||
<div className="bg-primary text-white">Content</div>
|
||||
```
|
||||
|
||||
**Tailwind v4:**
|
||||
```tsx
|
||||
// v4 may use CSS variables differently
|
||||
// Check the project's existing patterns
|
||||
<div className="bg-primary text-white">Content</div>
|
||||
```
|
||||
|
||||
**Common mistake:** Using v3 syntax in v4 projects or vice versa. Always verify the version first.
|
||||
|
||||
### Document Discovery
|
||||
|
||||
Create mental inventory of:
|
||||
- **Primary color(s)** and their usage
|
||||
- **Font families** (sans, serif, heading, mono)
|
||||
- **Common patterns** (button styles, card designs, spacing)
|
||||
- **Semantic names** (primary, secondary, accent vs blue-500, red-600)
|
||||
|
||||
## Critical Consistency Rules
|
||||
|
||||
### ALWAYS Follow These Rules
|
||||
|
||||
✅ **NEVER use emojis in storefront UI** - Always use icons or images instead
|
||||
|
||||
```tsx
|
||||
// ✅ CORRECT - Using icon component or image
|
||||
<button className="flex items-center gap-2">
|
||||
<ShoppingCartIcon className="w-5 h-5" />
|
||||
Add to Cart
|
||||
</button>
|
||||
|
||||
// ❌ WRONG - Using emoji
|
||||
<button>
|
||||
🛒 Add to Cart
|
||||
</button>
|
||||
```
|
||||
|
||||
**Why:** Emojis appear differently across platforms, lack professional appearance, and can cause accessibility issues. Use icon libraries (Heroicons, Lucide, Font Awesome) or SVG images instead.
|
||||
|
||||
✅ **USE existing design tokens** (colors, fonts, spacing from theme)
|
||||
|
||||
```tsx
|
||||
// ✅ CORRECT - Using theme colors
|
||||
<button className="bg-primary text-white hover:bg-primary-dark">
|
||||
Click Me
|
||||
</button>
|
||||
|
||||
// ❌ WRONG - Arbitrary colors when theme exists
|
||||
<button className="bg-[#3B82F6] text-white hover:bg-[#2563EB]">
|
||||
Click Me
|
||||
</button>
|
||||
```
|
||||
|
||||
✅ **USE existing font definitions**, not new font families
|
||||
|
||||
```tsx
|
||||
// ✅ CORRECT - Using theme font
|
||||
<h1 className="font-heading text-4xl font-bold">
|
||||
Welcome
|
||||
</h1>
|
||||
|
||||
// ❌ WRONG - Introducing new font
|
||||
<h1 className="font-['Montserrat'] text-4xl font-bold">
|
||||
Welcome
|
||||
</h1>
|
||||
```
|
||||
|
||||
✅ **MATCH patterns from existing components**
|
||||
|
||||
```tsx
|
||||
// If existing buttons use: bg-primary px-6 py-3 rounded-lg
|
||||
// New buttons should use the same pattern
|
||||
<button className="bg-primary px-6 py-3 rounded-lg">
|
||||
New Button
|
||||
</button>
|
||||
```
|
||||
|
||||
### NEVER Do These Things
|
||||
|
||||
❌ **DON'T introduce new colors without user approval**
|
||||
- If you need a color not in the theme, ASK first
|
||||
- Don't use arbitrary values like `bg-[#FF6B6B]` when theme has colors
|
||||
|
||||
❌ **DON'T add new fonts without user approval**
|
||||
- If current design uses Inter, don't add Montserrat without asking
|
||||
- Don't use `font-['NewFont']` syntax when theme fonts exist
|
||||
|
||||
❌ **DON'T use hard-coded values when theme tokens exist**
|
||||
- Use `bg-primary` not `bg-[#3B82F6]`
|
||||
- Use `p-6` not `p-[24px]`
|
||||
- Use `font-heading` not `font-['Poppins']`
|
||||
|
||||
❌ **DON'T create inconsistent patterns**
|
||||
- If buttons use `rounded-lg`, all buttons should
|
||||
- If cards use `shadow-md`, all cards should
|
||||
- If hover effects use `hover:bg-primary-dark`, be consistent
|
||||
|
||||
## When to Ask User Approval
|
||||
|
||||
**ALWAYS ask before:**
|
||||
|
||||
### 1. Adding New Color
|
||||
|
||||
```
|
||||
"I notice the current palette doesn't include an orange accent color.
|
||||
Should I add one, or would you prefer to use the existing accent color?"
|
||||
```
|
||||
|
||||
**Scenario:** You're building a promotional banner that needs an orange color, but theme only has blue/purple.
|
||||
|
||||
### 2. Adding New Font
|
||||
|
||||
```
|
||||
"The current design uses Inter for all text. Do you want me to add
|
||||
a different font for headings, or keep using Inter throughout?"
|
||||
```
|
||||
|
||||
**Scenario:** Building a hero section and wondering if headings should use a different font.
|
||||
|
||||
### 3. Changing Existing Definitions
|
||||
|
||||
```
|
||||
"Should I update the primary color to #3B82F6, or create a
|
||||
new color variant?"
|
||||
```
|
||||
|
||||
**Scenario:** Current primary is #2563EB but new design mockup shows #3B82F6.
|
||||
|
||||
### 4. Creating New Pattern
|
||||
|
||||
```
|
||||
"The current components don't have a ghost button style (transparent with border).
|
||||
Should I create one, or use an existing button variant?"
|
||||
```
|
||||
|
||||
**Scenario:** Need a subtle button style that doesn't exist yet.
|
||||
|
||||
### DON'T Ask About
|
||||
|
||||
❌ Standard web dev decisions (responsive breakpoints, hover effects)
|
||||
❌ Component structure or layout choices
|
||||
❌ Accessibility patterns (AI agents know WCAG)
|
||||
❌ Using existing theme colors/fonts in new ways
|
||||
|
||||
## New Project Setup
|
||||
|
||||
When starting a new project WITHOUT existing theme:
|
||||
|
||||
### Ask User These Questions
|
||||
|
||||
**1. Brand Colors:**
|
||||
```
|
||||
"What are your brand colors? Please provide:
|
||||
- Primary color (main brand color)
|
||||
- Secondary color (optional)
|
||||
- Any specific hex codes or color preferences?"
|
||||
```
|
||||
|
||||
**2. Font Preferences:**
|
||||
```
|
||||
"Do you have font preferences?
|
||||
- Modern and clean (Inter, Poppins)
|
||||
- Classic and professional (Merriweather, Lora)
|
||||
- Specific fonts?
|
||||
- Or should I choose appropriate fonts?"
|
||||
```
|
||||
|
||||
**3. Design Style:**
|
||||
```
|
||||
"What design style do you prefer?
|
||||
- Minimal (lots of whitespace, clean lines)
|
||||
- Bold (vibrant colors, large typography)
|
||||
- Professional (conservative, trust-focused)
|
||||
- Modern (rounded corners, gradients, shadows)"
|
||||
```
|
||||
|
||||
**4. Reference Sites (Optional):**
|
||||
```
|
||||
"Do you have 2-3 example websites you like the look of?
|
||||
This helps me understand your aesthetic preferences."
|
||||
```
|
||||
|
||||
### Setup Theme Configuration
|
||||
|
||||
After gathering preferences, configure Tailwind theme:
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
export default {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#3B82F6', // User's primary color
|
||||
secondary: '#8B5CF6', // User's secondary
|
||||
accent: '#F59E0B', // Accent if needed
|
||||
// Full scales if sophisticated design
|
||||
brand: {
|
||||
50: '#eff6ff',
|
||||
500: '#3b82f6',
|
||||
900: '#1e3a8a',
|
||||
}
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'system-ui', 'sans-serif'],
|
||||
heading: ['Poppins', 'sans-serif'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**Use Tailwind CSS for all new projects** - industry standard for ecommerce, highly customizable, excellent DX.
|
||||
|
||||
## Decision Tree
|
||||
|
||||
**When creating any component:**
|
||||
|
||||
```
|
||||
1. Does a theme configuration exist?
|
||||
├─ Yes → Extract colors/fonts from theme
|
||||
│ Use existing tokens for new component
|
||||
└─ No → Ask user for brand preferences
|
||||
Create theme configuration
|
||||
|
||||
2. Are there similar existing components?
|
||||
├─ Yes → Follow their patterns exactly
|
||||
│ (spacing, colors, hover states)
|
||||
└─ No → Check ANY existing components
|
||||
Extract general patterns (spacing scale, hover effects)
|
||||
|
||||
3. Do you need a color/font not in theme?
|
||||
├─ Yes → ASK user for approval before adding
|
||||
│ Explain why you need it
|
||||
└─ No → Proceed with existing tokens
|
||||
|
||||
4. Are you unsure about a design pattern?
|
||||
├─ Yes → Check 2-3 existing components for guidance
|
||||
│ Follow majority pattern
|
||||
└─ No → Implement using theme tokens
|
||||
Maintain consistency with existing components
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### ❌ Using Arbitrary Values When Theme Exists
|
||||
|
||||
**Problem:** Using `bg-[#3B82F6]` when `bg-primary` exists.
|
||||
|
||||
**Why it's wrong:** Bypasses theme, creates inconsistency, harder to maintain.
|
||||
|
||||
**Fix:** Always use semantic names from theme.
|
||||
|
||||
### ❌ Introducing New Colors Without Permission
|
||||
|
||||
**Problem:** Adding `text-orange-500` when theme doesn't have orange.
|
||||
|
||||
**Why it's wrong:** User may not want orange in their brand, creates color chaos.
|
||||
|
||||
**Fix:** Ask user first: "Should I add an orange color, or use existing accent?"
|
||||
|
||||
### ❌ Not Checking Existing Patterns
|
||||
|
||||
**Problem:** Creating buttons with `rounded-full` when all other buttons use `rounded-lg`.
|
||||
|
||||
**Why it's wrong:** Visual inconsistency confuses users.
|
||||
|
||||
**Fix:** Check 2-3 existing buttons, use same rounding.
|
||||
|
||||
### ❌ Adding Fonts Without Permission
|
||||
|
||||
**Problem:** Using `font-['Montserrat']` when theme uses Inter everywhere.
|
||||
|
||||
**Why it's wrong:** Fonts are brand identity - can't arbitrarily change.
|
||||
|
||||
**Fix:** Use existing `font-heading` or `font-sans`, or ask to add Montserrat.
|
||||
|
||||
### ❌ Using Inline Styles Instead of Theme
|
||||
|
||||
**Problem:** `style={{ backgroundColor: '#3B82F6', padding: '24px' }}`
|
||||
|
||||
**Why it's wrong:** Bypasses Tailwind theme, not responsive, harder to maintain.
|
||||
|
||||
**Fix:** Use Tailwind classes: `bg-primary p-6`
|
||||
|
||||
### ❌ Mixing Tailwind v3 and v4 Syntax
|
||||
|
||||
**Problem:** Using Tailwind v3 syntax in a v4 project, or vice versa.
|
||||
|
||||
**Why it's wrong:** Different versions have different configuration and syntax patterns. Mixing them causes build errors and unexpected styling behavior.
|
||||
|
||||
**Fix:** Check `package.json` for Tailwind version first. Look at existing components to understand the syntax patterns used in the project. Match the version-specific patterns consistently.
|
||||
|
||||
### ❌ Inconsistent Interactive States
|
||||
|
||||
**Problem:** Some buttons use `hover:bg-primary-600`, others use `hover:brightness-110`.
|
||||
|
||||
**Why it's wrong:** Inconsistent user experience.
|
||||
|
||||
**Fix:** Check existing buttons, use same hover pattern everywhere.
|
||||
|
||||
### ❌ Creating Theme Changes Without Approval
|
||||
|
||||
**Problem:** Adding new color to `tailwind.config.ts` without asking.
|
||||
|
||||
**Why it's wrong:** Theme changes affect entire project, need user agreement.
|
||||
|
||||
**Fix:** Ask first, explain rationale, get approval.
|
||||
|
||||
## Summary Checklist
|
||||
|
||||
**Before creating any component:**
|
||||
|
||||
- [ ] **Detected Tailwind CSS version (v3 or v4) from package.json**
|
||||
- [ ] Checked for existing theme configuration (Tailwind config or CSS variables)
|
||||
- [ ] Extracted existing colors and documented them
|
||||
- [ ] Extracted existing fonts and documented them
|
||||
- [ ] Reviewed 2-3 existing components for patterns
|
||||
- [ ] Identified spacing scale, border radius, shadow patterns
|
||||
- [ ] Confirmed I'm using theme tokens, not arbitrary values
|
||||
- [ ] Matched hover/focus states from existing components
|
||||
- [ ] Verified color contrast meets WCAG 2.1 AA (4.5:1 for text) - Use [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
|
||||
- [ ] Asked user before adding any new colors or fonts
|
||||
- [ ] Maintained visual consistency across all components
|
||||
|
||||
**This is about CONSISTENCY, not creating new designs.** Match what exists, ask before changing.
|
||||
@@ -0,0 +1,307 @@
|
||||
# Promotions Feature
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Promotion Types and When to Use](#promotion-types-and-when-to-use)
|
||||
- [Sale Price Display](#sale-price-display)
|
||||
- [Promo Code Input](#promo-code-input)
|
||||
- [Free Shipping Threshold](#free-shipping-threshold)
|
||||
- [Promotional Banners](#promotional-banners)
|
||||
- [Countdown Timers](#countdown-timers)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Promotions are temporary price reductions, discounts, or special offers designed to drive sales and incentivize purchases. Effective promotion UI clearly communicates value, creates urgency, and makes redemption easy.
|
||||
|
||||
**Backend Integration (CRITICAL):**
|
||||
|
||||
All promotion logic and data must come from the ecommerce backend. Do this based on backend integrated. Fetch active promotions, discount codes, and price rules from backend API. Never hardcode promotion logic in frontend.
|
||||
|
||||
### Key Ecommerce Requirements
|
||||
|
||||
- Clear discount communication (strikethrough pricing, percentage off)
|
||||
- Promo code input (cart/checkout)
|
||||
- Free shipping threshold progress (increase AOV)
|
||||
- Countdown timers (create urgency)
|
||||
- Automatic discount application
|
||||
- Sale badges (product discovery)
|
||||
|
||||
### Purpose
|
||||
|
||||
**Conversion optimization:**
|
||||
- Drive sales and increase conversion rate
|
||||
- Increase average order value (free shipping thresholds, tiered discounts)
|
||||
- Acquire new customers (first-order discounts)
|
||||
- Create urgency (limited-time offers)
|
||||
- Clear inventory (seasonal sales)
|
||||
- Reward loyalty (VIP codes, member discounts)
|
||||
|
||||
## Promotion Types and When to Use
|
||||
|
||||
### Sales (Price Reductions)
|
||||
|
||||
**What it is**: Select products with reduced prices, automatically applied. No code needed.
|
||||
|
||||
**Use when:**
|
||||
- Seasonal sales (Black Friday, holiday sales)
|
||||
- Clearance or end-of-season inventory
|
||||
- Product-specific promotions
|
||||
- You want reduced prices visible on product pages (increases click-through)
|
||||
|
||||
**Display:**
|
||||
- Strikethrough original price (provides context for savings)
|
||||
- Sale price bold and prominent (red or brand color)
|
||||
- Sale badge on product cards ("Sale", "30% Off")
|
||||
|
||||
**Medusa implementation:**
|
||||
Use Price Lists with special prices for products. Provides automatic strikethrough pricing in cart and on product pages.
|
||||
|
||||
### Discount Codes
|
||||
|
||||
**What it is**: Customer enters code to unlock discount (percentage, fixed amount, or free shipping).
|
||||
|
||||
**Use when:**
|
||||
- Newsletter signups ("Get 10% off with WELCOME10")
|
||||
- VIP or loyalty program members (exclusive codes)
|
||||
- Targeted marketing campaigns (email, social media)
|
||||
- First-time customer incentives
|
||||
- Friends and family discounts (limited distribution)
|
||||
|
||||
**Display:**
|
||||
- Promo code input field in cart/checkout
|
||||
- Success message: "Code applied: WELCOME10"
|
||||
- Discount shown in order summary with code name
|
||||
- Remove option (X icon or "Remove" link)
|
||||
|
||||
**Medusa implementation:**
|
||||
Discount/promo code system with advanced logic (order-level discounts, usage limits, expiration dates).
|
||||
|
||||
### Automatic Discounts
|
||||
|
||||
**What it is**: Discount automatically applied when conditions met. No code entry required.
|
||||
|
||||
**Use when:**
|
||||
- Free shipping thresholds ("Free shipping over $50")
|
||||
- Volume discounts ("Spend $100, get $20 off")
|
||||
- Buy One Get One (BOGO) offers
|
||||
- Encouraging larger cart values (increase AOV)
|
||||
|
||||
**Display:**
|
||||
- Banner announcing the promotion
|
||||
- Progress indicator toward threshold (see Free Shipping Threshold section)
|
||||
- "Discount applied" message in cart
|
||||
- Automatic addition to order summary
|
||||
|
||||
### Buy X, Get Y (BOGO)
|
||||
|
||||
**What it is**: Purchase certain products to unlock free/discounted items.
|
||||
|
||||
**Use when:**
|
||||
- Moving inventory (clear out slow-moving products)
|
||||
- Cross-selling related products ("Buy sunscreen, get beach bag 50% off")
|
||||
- Increasing units per transaction
|
||||
|
||||
**Display:**
|
||||
- Clear promotion text on product page ("Buy 2, Get 1 Free")
|
||||
- Free/discounted item shown in cart with explanation
|
||||
- Discount line in order summary
|
||||
|
||||
**Medusa implementation:**
|
||||
Buy X Get Y automatic discount. Free/discounted item must be added to cart to activate.
|
||||
|
||||
## Sale Price Display
|
||||
|
||||
### Strikethrough Pricing Pattern
|
||||
|
||||
**Format:**
|
||||
```
|
||||
$49.99 $34.99
|
||||
(Original, strikethrough) (Sale price, bold)
|
||||
```
|
||||
|
||||
**Design:**
|
||||
- Original price: Strikethrough, muted gray color, smaller
|
||||
- Sale price: Bold, larger, red or accent color
|
||||
- Clear visual hierarchy (sale price dominates)
|
||||
|
||||
**Placement:**
|
||||
- Product cards: Below image
|
||||
- Product page: Near "Add to Cart" button
|
||||
- Cart: Item price column
|
||||
|
||||
### Percentage Off Display
|
||||
|
||||
Show savings to emphasize value.
|
||||
|
||||
**Options:**
|
||||
- "Save 30%" badge
|
||||
- "30% off" label
|
||||
- "$15 off" (absolute savings)
|
||||
|
||||
**Placement:**
|
||||
- Badge on product image (top-left or top-right corner)
|
||||
- Near price (inline or below)
|
||||
- In cart summary ("Total savings: $45")
|
||||
|
||||
### Sale Badge
|
||||
|
||||
Bright badge on product image (red, orange, yellow) in top corner. 48-64px desktop, 40-48px mobile. Text: "Sale", "30% Off", or "Save $15".
|
||||
|
||||
## Promo Code Input
|
||||
|
||||
### Placement and Design
|
||||
|
||||
**Location:**
|
||||
Cart page order summary or checkout page. Position in right sidebar (desktop) or below items (mobile).
|
||||
|
||||
**Layout:**
|
||||
- Label: "Promo code" or "Discount code"
|
||||
- Text input (200-280px desktop, full-width mobile)
|
||||
- "Apply" button inline or stacked (mobile)
|
||||
- Auto-uppercase on submit (codes usually uppercase)
|
||||
|
||||
**Expandable pattern (optional):**
|
||||
"Have a promo code?" link that expands to show input. Saves vertical space, reduces visual clutter.
|
||||
|
||||
### Success and Error States
|
||||
|
||||
**Success:**
|
||||
- Green checkmark or success message: "Code applied: WELCOME10"
|
||||
- Discount shown in order summary with code name: "Discount (WELCOME10) -$10.00"
|
||||
- Remove option: X icon or "Remove" link
|
||||
- Update cart total immediately
|
||||
|
||||
**Error:**
|
||||
- Red error message below input: "Invalid code", "Code expired", or "Minimum purchase not met"
|
||||
- Input remains visible for retry
|
||||
- Don't clear input field (user may have typo)
|
||||
|
||||
**Applied code display in order summary:**
|
||||
```
|
||||
Subtotal $100.00
|
||||
Discount (WELCOME10) -$10.00
|
||||
Shipping $5.00
|
||||
─────────────────────
|
||||
Total $95.00
|
||||
```
|
||||
|
||||
## Free Shipping Threshold
|
||||
|
||||
**Purpose (CRITICAL)**: Increase average order value by encouraging customers to add more items to reach free shipping.
|
||||
|
||||
### Progress Bar Pattern
|
||||
|
||||
**Display in cart:**
|
||||
- "Add $25 more for FREE SHIPPING"
|
||||
- Horizontal progress bar showing proximity to threshold
|
||||
- Updates automatically as cart value changes
|
||||
- Green when threshold reached
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Add $25.00 more for FREE SHIPPING
|
||||
[███████░░░░░░░░] 50%
|
||||
```
|
||||
|
||||
**When threshold met:**
|
||||
- "You've unlocked free shipping!" (success message)
|
||||
- Green checkmark or badge
|
||||
- Crossed-out shipping charge in order summary
|
||||
|
||||
**Why it works:**
|
||||
- Visualizes proximity to goal (loss aversion)
|
||||
- Increases AOV by 15-30% on average
|
||||
- Reduces cart abandonment (free shipping is top reason to complete purchase)
|
||||
|
||||
### Free Shipping Banner
|
||||
|
||||
Sitewide announcement: "Free shipping on orders over $50". Display in top banner or near cart icon. Visible on all pages for awareness.
|
||||
|
||||
## Promotional Banners
|
||||
|
||||
### Top Banner
|
||||
|
||||
Full-width strip at top of page (48-64px height). Bright color contrasting with navbar. Short message: "Free shipping on orders over $50" or "Sale: Up to 50% off - Shop Now".
|
||||
|
||||
**Position:**
|
||||
- Above navbar (most common)
|
||||
- Below navbar (alternative)
|
||||
- Sticky (stays visible on scroll, optional)
|
||||
|
||||
**CTA:**
|
||||
Link to sale page ("Shop Now", "Learn More") or whole banner clickable.
|
||||
|
||||
### Hero Banner
|
||||
|
||||
Large hero section on homepage with promotional message. Background image, headline ("Black Friday Sale"), subheading ("Up to 60% off sitewide"), CTA button ("Shop the Sale"), optional countdown timer.
|
||||
|
||||
### Inline Banners
|
||||
|
||||
Within page content (product pages, cart). Examples: Free shipping reminder on cart page, "Sale ends soon" on product page. Less prominent than hero.
|
||||
|
||||
## Countdown Timers
|
||||
|
||||
Use for time-sensitive promotions to create urgency and FOMO.
|
||||
|
||||
**When to use:**
|
||||
- Flash sales (24-hour sales)
|
||||
- Limited-time offers
|
||||
- Holiday promotions
|
||||
- Never for permanent sales (fake urgency harms trust)
|
||||
|
||||
**Display format:**
|
||||
- "Sale ends in: 2d 14h 32m 15s"
|
||||
- Or simpler: "Ends in 2 days"
|
||||
- Or: "Hurry! Only 14 hours left"
|
||||
|
||||
**Placement:**
|
||||
Top banner, product page near price, cart page, or hero section.
|
||||
|
||||
**Implementation:**
|
||||
Server-side time to prevent client manipulation, auto-hide when expired, update in real-time.
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Top banner:**
|
||||
Shorter text (fewer words), smaller height (40-48px), dismissible (X button).
|
||||
|
||||
**Sale badges:**
|
||||
Slightly smaller (40-48px), still clearly visible, don't obstruct product image.
|
||||
|
||||
**Promo code input:**
|
||||
Full-width input and button, stacked layout (input above button), large touch targets (48px height), expandable section to save space.
|
||||
|
||||
**Countdown timer:**
|
||||
Simplified format ("Ends in 14 hours" vs full d:h:m:s), larger text for readability.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Strikethrough original price for sales
|
||||
- [ ] Sale price bold, prominent, colored
|
||||
- [ ] Sale badges on product images (40-64px)
|
||||
- [ ] Percentage off displayed ("30% Off")
|
||||
- [ ] Promo code input field in cart/checkout
|
||||
- [ ] "Apply" button next to promo input
|
||||
- [ ] Success message after applying code
|
||||
- [ ] Error message for invalid codes
|
||||
- [ ] Applied code displayed in order summary with name
|
||||
- [ ] Remove code option (X icon or "Remove" link)
|
||||
- [ ] Total savings highlighted in cart
|
||||
- [ ] Free shipping progress bar (if applicable)
|
||||
- [ ] Progress updates as cart value changes
|
||||
- [ ] Success message when threshold met
|
||||
- [ ] Countdown timer for time-limited offers (server-side)
|
||||
- [ ] Promotional banners (top banner, hero)
|
||||
- [ ] Backend integration (fetch promotions from API)
|
||||
- [ ] Mobile: Full-width promo input, stacked layout
|
||||
- [ ] Mobile: Large touch targets (48px)
|
||||
- [ ] Expandable promo section (optional, saves space)
|
||||
- [ ] ARIA labels on promo input
|
||||
- [ ] Screen reader announcements for price changes
|
||||
- [ ] Keyboard accessible (Tab, Enter)
|
||||
- [ ] High contrast text (4.5:1 minimum)
|
||||
@@ -0,0 +1,230 @@
|
||||
# Wishlist Feature
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Backend Support Check](#backend-support-check)
|
||||
- [Wishlist Button](#wishlist-button)
|
||||
- [Adding and Removing](#adding-and-removing)
|
||||
- [Wishlist Page](#wishlist-page)
|
||||
- [Guest vs Logged-In Users](#guest-vs-logged-in-users)
|
||||
- [Navigation Icon](#navigation-icon)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
A wishlist (also called favorites or save for later) allows customers to save products they're interested in for future purchase. This feature helps organize shopping, track desired items, and increases return visits and conversions.
|
||||
|
||||
### Key Ecommerce Benefits
|
||||
|
||||
**Why wishlists matter:**
|
||||
- Increase return visits (users come back to check wishlist)
|
||||
- Reduce cart abandonment (save for later instead of abandoning)
|
||||
- Gift planning (save items for gift lists, share with others)
|
||||
- Price tracking (users monitor items for sales - remarketing opportunity)
|
||||
- Engagement metric (shows product interest for analytics)
|
||||
|
||||
**Conversion impact:**
|
||||
- Users with wishlists have 2-3x higher lifetime value
|
||||
- Wishlist-to-purchase conversion: 20-30% on average
|
||||
- Email reminders about wishlist items: 15-25% click-through rate
|
||||
|
||||
## Backend Support Check
|
||||
|
||||
**CRITICAL: Only implement wishlist UI if your ecommerce backend supports wishlist functionality.**
|
||||
|
||||
Before implementing:
|
||||
1. **Check backend API** - Verify wishlist endpoints exist (or ask user)
|
||||
2. **Authentication** - Confirm if login required for wishlist storage
|
||||
3. **Test operations** - Verify add/remove/fetch functionality works
|
||||
|
||||
**Medusa users:**
|
||||
Medusa core doesn't include wishlist by default. Install the Wishlist plugin from Medusa examples repository. Plugin provides full wishlist functionality with API endpoints.
|
||||
|
||||
**General backends:**
|
||||
Wishlist typically requires user authentication. API endpoints needed:
|
||||
- GET /wishlist (fetch user's wishlist)
|
||||
- POST /wishlist (add item)
|
||||
- DELETE /wishlist/{id} (remove item)
|
||||
|
||||
**If backend doesn't support wishlist:**
|
||||
Don't implement the feature. localStorage-only wishlist creates poor UX (lost on device switch, no sync, no remarketing).
|
||||
|
||||
## Wishlist Button
|
||||
|
||||
### Design and States
|
||||
|
||||
**Heart icon** (universal symbol):
|
||||
- Outline heart: Not in wishlist
|
||||
- Filled heart: In wishlist
|
||||
- 24-32px on product cards, 32-40px on product page
|
||||
|
||||
**Colors:**
|
||||
- Outline: Gray or black
|
||||
- Filled: Red, pink, or brand color
|
||||
- High contrast against product image
|
||||
|
||||
### Placement
|
||||
|
||||
**Product cards:**
|
||||
Top-right corner of product image, always visible (not hover-only), 16px margin from edges.
|
||||
|
||||
**Product detail page:**
|
||||
Near "Add to Cart" button, or above product image, or with sharing options. Optional text label: "Add to Wishlist" or icon-only.
|
||||
|
||||
## Adding and Removing
|
||||
|
||||
### Adding to Wishlist
|
||||
|
||||
**Flow:**
|
||||
1. User clicks heart icon
|
||||
2. Show loading state briefly
|
||||
3. Send API request to add item
|
||||
4. Update icon to filled state
|
||||
5. Show success feedback (toast: "Added to wishlist" or subtle animation)
|
||||
6. Update navigation wishlist badge (+1)
|
||||
|
||||
**Optimistic UI:**
|
||||
Update icon immediately, revert if API fails. Provides instant feedback.
|
||||
|
||||
**Error handling:**
|
||||
Show error toast ("Failed to add to wishlist"), revert icon to outline, allow retry.
|
||||
|
||||
**Variant handling:**
|
||||
Save specific variant (size, color) if selected on product page. On product cards, save default variant.
|
||||
|
||||
### Removing from Wishlist
|
||||
|
||||
**From product card/page:**
|
||||
Click filled heart → changes to outline → toast: "Removed from wishlist" → update badge (-1).
|
||||
|
||||
**From wishlist page:**
|
||||
X icon in corner of product card or "Remove" button → item fades out. Optional: Undo action in toast (5 seconds).
|
||||
|
||||
**Confirmation:**
|
||||
Generally not needed (low stakes, easily reversible). Only confirm for bulk actions ("Clear all").
|
||||
|
||||
## Wishlist Page
|
||||
|
||||
### Layout
|
||||
|
||||
**Heading:**
|
||||
"My Wishlist" or "Favorites" with item count ("12 items saved").
|
||||
|
||||
**Product grid:**
|
||||
Similar to product listing page. Product cards with images, titles, current prices (may differ from when added), stock status.
|
||||
|
||||
**Empty state:**
|
||||
"Your wishlist is empty" with "Start Shopping" CTA.
|
||||
|
||||
### Product Card Information
|
||||
|
||||
Display per item:
|
||||
- Product image (linked to product page)
|
||||
- Product title (linked)
|
||||
- Current price (may show sale price if on sale now)
|
||||
- Original price if on sale (strikethrough)
|
||||
- Variant details (size, color if saved)
|
||||
- Stock status: In stock (green), Out of stock (red, "Notify me" option), Low stock ("Only 2 left")
|
||||
- **"Add to Cart" button** (CRITICAL - conversion path)
|
||||
- Remove button (X icon)
|
||||
|
||||
### Actions and Conversion
|
||||
|
||||
**Add to Cart (CRITICAL):**
|
||||
"Add to Cart" button on each item. Adds item to cart **without removing from wishlist** (user may want both). Success toast: "Added to cart". Don't navigate away (stay on wishlist page).
|
||||
|
||||
**Tradeoff:**
|
||||
- **Keep in wishlist** (recommended): User tracks desired items, can reorder easily
|
||||
- **Move to cart**: Removes from wishlist after adding - simpler but limits reordering
|
||||
|
||||
**Stock handling:**
|
||||
If out of stock, disable "Add to Cart" and show "Notify me when back in stock" option (if backend supports).
|
||||
|
||||
## Guest vs Logged-In Users
|
||||
|
||||
### Decision: Require Login or Use localStorage?
|
||||
|
||||
**Require login (Recommended):**
|
||||
|
||||
**Why:**
|
||||
- Wishlist requires persistent storage across devices
|
||||
- Enables email reminders and price drop notifications
|
||||
- Better user experience (never lost)
|
||||
- Cleaner data for analytics and remarketing
|
||||
- Avoids confusion of lost wishlist items
|
||||
|
||||
**Implementation:**
|
||||
Click wishlist → Show login prompt modal: "Log in to save your wishlist". Include "Sign Up" button. Clear benefit: "Save items across all your devices".
|
||||
|
||||
**localStorage approach (Not Recommended):**
|
||||
- Device-specific only (lost on device switch)
|
||||
- Lost if user clears browser data
|
||||
- No remarketing opportunities
|
||||
- No email reminders
|
||||
- Creates poor UX expectations
|
||||
|
||||
**Exception:**
|
||||
If backend doesn't support authenticated wishlist, consider not implementing feature at all rather than localStorage-only.
|
||||
|
||||
## Navigation Icon
|
||||
|
||||
### Placement and Design
|
||||
|
||||
**Position:**
|
||||
Top navigation bar, between search icon and cart icon. Or: In user account dropdown menu.
|
||||
|
||||
**Icon:**
|
||||
Heart icon (outline or filled if items in wishlist). 24-32px size, consistent with cart icon.
|
||||
|
||||
**Badge count:**
|
||||
Small circle with number showing total items in wishlist. Red or brand color, positioned top-right of heart icon.
|
||||
|
||||
**Link behavior:**
|
||||
Navigates to wishlist page on click. Dropdown less common for wishlist (unlike cart popup).
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Heart button:**
|
||||
Larger touch target (44px minimum), positioned in corner of product image, clear tap feedback (scale or color change).
|
||||
|
||||
**Wishlist page:**
|
||||
Single column product grid, stack cards vertically, full-width "Add to Cart" buttons, large remove buttons (44px touch target).
|
||||
|
||||
**Navigation icon:**
|
||||
Heart icon in mobile navbar or hamburger menu, with badge count.
|
||||
|
||||
**Login prompt:**
|
||||
If guest clicks wishlist, show bottom sheet (less disruptive than full modal) with "Log in to save your wishlist" message.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Backend API support verified before implementing
|
||||
- [ ] Heart icon on product cards (top-right corner)
|
||||
- [ ] Heart icon on product detail page
|
||||
- [ ] Clear filled vs outline states
|
||||
- [ ] Toast notification on add/remove
|
||||
- [ ] Wishlist icon in navigation with badge count
|
||||
- [ ] Wishlist page with product grid
|
||||
- [ ] Product info: image, title, current price, stock status
|
||||
- [ ] Variant details if saved (size, color)
|
||||
- [ ] "Add to Cart" button on each wishlist item
|
||||
- [ ] Add to cart without removing from wishlist
|
||||
- [ ] Remove button (X icon) on each item
|
||||
- [ ] Empty wishlist state ("Start Shopping" CTA)
|
||||
- [ ] Login required for persistent wishlist
|
||||
- [ ] Guest user login prompt on wishlist click
|
||||
- [ ] Stock status indicators (in stock, out of stock, low stock)
|
||||
- [ ] Out of stock: Disable add to cart, show "Notify me"
|
||||
- [ ] Mobile: 44px touch targets
|
||||
- [ ] Mobile: Single column layout
|
||||
- [ ] Optimistic UI (instant feedback)
|
||||
- [ ] Error handling for failed API requests
|
||||
- [ ] Loading states during add/remove
|
||||
- [ ] Button aria-label ("Add to wishlist" / "Remove from wishlist")
|
||||
- [ ] aria-pressed attribute on heart button
|
||||
- [ ] Keyboard accessible (Tab, Enter/Space)
|
||||
- [ ] Screen reader announcements for add/remove
|
||||
@@ -0,0 +1,380 @@
|
||||
# Account Pages Layout
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Account Dashboard](#account-dashboard)
|
||||
- [Order Management](#order-management)
|
||||
- [Saved Addresses](#saved-addresses)
|
||||
- [Payment Methods](#payment-methods)
|
||||
- [Profile and Security](#profile-and-security)
|
||||
- [Email Preferences](#email-preferences)
|
||||
- [Navigation and Layout](#navigation-and-layout)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Account pages allow customers to manage orders, save addresses, update preferences, and view order history. Well-designed account pages improve repeat purchase rates and reduce support inquiries.
|
||||
|
||||
**Backend Integration (CRITICAL):**
|
||||
|
||||
All customer data (orders, addresses, profile, payment methods) must be fetched from the ecommerce backend. Change this based on backend integrated. Never hardcode or mock account data. Consult backend documentation for:
|
||||
- Customer data endpoints (profile, preferences)
|
||||
- Order history and details endpoints
|
||||
- Address CRUD operations
|
||||
- Payment method storage (if supported)
|
||||
- Authentication requirements
|
||||
|
||||
### Key Ecommerce Requirements
|
||||
|
||||
- Order history with status tracking (builds trust)
|
||||
- Saved addresses (checkout optimization - reduces friction)
|
||||
- Reorder functionality (increases repeat purchases)
|
||||
- Order tracking integration
|
||||
- Email preference controls (compliance and user control)
|
||||
- Secure authentication and session management
|
||||
|
||||
### Purpose
|
||||
|
||||
**Primary ecommerce functions:**
|
||||
- Reduce checkout friction (saved addresses, payment methods)
|
||||
- Increase repeat purchases (order history, reorder button)
|
||||
- Reduce support load (order tracking, self-service returns)
|
||||
- Build trust (order transparency, delivery updates)
|
||||
- Retain customers (easy account management)
|
||||
|
||||
## Account Dashboard
|
||||
|
||||
Landing page after login. Purpose: Quick access to recent activity and common actions.
|
||||
|
||||
**Display (prioritize recent orders):**
|
||||
- Welcome message with customer name
|
||||
- Recent orders (3-5 most recent with status)
|
||||
- Quick actions: Track order, Reorder, Manage addresses
|
||||
- Account summary (saved addresses count, loyalty points)
|
||||
|
||||
**Reorder functionality (CRITICAL for repeat purchases):**
|
||||
- Check first that feature is available in the admin.
|
||||
- "Reorder" button on each order card
|
||||
- Adds same items to cart (check stock availability first)
|
||||
- Success feedback (cart updated with X items)
|
||||
- Don't navigate away (stay on dashboard)
|
||||
|
||||
**Example dashboard:**
|
||||
```
|
||||
Welcome back, Sarah!
|
||||
|
||||
Recent Orders
|
||||
- Order #12345 - Delivered (Jan 28) - $89.99 [Reorder]
|
||||
- Order #12344 - In Transit (Jan 27) - $124.50 [Track Order]
|
||||
- Order #12343 - Processing (Jan 26) - $45.00
|
||||
|
||||
[View All Orders →]
|
||||
|
||||
Quick Actions
|
||||
[Track Order] [Manage Addresses] [Contact Support]
|
||||
```
|
||||
|
||||
## Order Management
|
||||
|
||||
### Order History
|
||||
|
||||
Display all past orders with filtering and search.
|
||||
|
||||
**Order card essentials:**
|
||||
- Order number (clickable to details page)
|
||||
- Order date and status badge (Processing, Shipped, Delivered)
|
||||
- Total amount
|
||||
- First 2-3 product thumbnails
|
||||
- Quick actions: Track, View Details, Reorder, Invoice
|
||||
|
||||
**Status indicators (color-coded):**
|
||||
- Processing: Yellow/Orange
|
||||
- Shipped: Blue
|
||||
- Delivered: Green
|
||||
- Cancelled: Gray/Red
|
||||
|
||||
**Filtering and search:**
|
||||
- Date range (Last 30 days, Last 6 months, All time)
|
||||
- Status filter (All, Processing, Shipped, Delivered)
|
||||
- Search by order number or product name
|
||||
|
||||
**Sorting:**
|
||||
- Most recent first (default)
|
||||
- Oldest first
|
||||
- Highest/lowest price
|
||||
|
||||
**Pagination:**
|
||||
Show 10-20 orders per page with pagination controls. Alternative: "Load More" button (better mobile UX).
|
||||
|
||||
### Order Details View
|
||||
|
||||
Full order information page.
|
||||
|
||||
**Display:**
|
||||
- Order number, date, status with progress timeline
|
||||
- Tracking number with carrier link (if shipped)
|
||||
- Estimated delivery date
|
||||
|
||||
**Status timeline (builds trust):**
|
||||
```
|
||||
✓ Order Placed (Jan 27, 9:45 AM)
|
||||
✓ Processing (Jan 27, 10:30 AM)
|
||||
✓ Shipped (Jan 28, 2:15 PM)
|
||||
○ Out for Delivery
|
||||
○ Delivered
|
||||
```
|
||||
|
||||
**Order information:**
|
||||
- Items ordered (image, name, variant, quantity, price)
|
||||
- Pricing breakdown (subtotal, shipping, tax, discounts, total)
|
||||
- Shipping address and method
|
||||
- Billing address
|
||||
- Payment method (last 4 digits)
|
||||
|
||||
**Order actions:**
|
||||
- Track shipment (link to carrier tracking page)
|
||||
- Download invoice/receipt (PDF)
|
||||
- Request return (if eligible and backend supports)
|
||||
- Reorder items
|
||||
- Contact support about order
|
||||
|
||||
### Reorder Functionality (Ecommerce-Specific)
|
||||
|
||||
**Purpose**: Increase repeat purchases by making it easy to reorder past purchases.
|
||||
|
||||
**Implementation:**
|
||||
- "Reorder" button on order cards and order details
|
||||
- Check stock availability before adding to cart
|
||||
- Handle discontinued products gracefully (skip or notify)
|
||||
- Add all available items to cart
|
||||
- Success message: "5 items added to cart" (or "3 of 5 items added - 2 unavailable")
|
||||
- Stay on current page (don't navigate away)
|
||||
|
||||
**Tradeoff**: Auto-add to cart (friction-free) vs redirect to cart page (let user review first). Recommend auto-add with clear success feedback.
|
||||
|
||||
## Saved Addresses
|
||||
|
||||
**Purpose (CRITICAL)**: Reduce checkout friction and increase conversion. Saved addresses make repeat purchases faster and easier.
|
||||
|
||||
### Why Addresses Matter
|
||||
|
||||
**Conversion optimization:**
|
||||
- Saved addresses reduce checkout time by 50%+ (no retyping)
|
||||
- Default address selection streamlines checkout flow
|
||||
- Reduces form abandonment (fewer fields to fill)
|
||||
- Increases repeat purchase rate (easier checkout)
|
||||
|
||||
**Backend integration:**
|
||||
Fetch, create, update, and delete addresses via backend API. Do this based on backend integrated.
|
||||
|
||||
### Address Book Display
|
||||
|
||||
**Saved addresses list:**
|
||||
- All saved addresses
|
||||
- Default address indicator (badge: "Default Shipping" or star icon)
|
||||
- Address preview: Name, street, city, state, zip
|
||||
- Quick actions: Edit, Delete, Set as Default
|
||||
|
||||
**Default address behavior:**
|
||||
- One default shipping address
|
||||
- One default billing address (separate or same)
|
||||
- Used automatically at checkout (user can change)
|
||||
- Setting new default updates previous default
|
||||
|
||||
### Add/Edit Address Form
|
||||
|
||||
Collect standard shipping information. Key considerations:
|
||||
|
||||
**Required fields:**
|
||||
- Full name (or first + last)
|
||||
- Address line 1
|
||||
- City, State/Province, ZIP/Postal code
|
||||
- Country
|
||||
- Phone number (recommended for delivery coordination)
|
||||
|
||||
**Optional enhancements:**
|
||||
- Address label (Home, Work) for easy identification
|
||||
- Address autocomplete API (Google Places) for accuracy
|
||||
- "Set as default" checkbox
|
||||
|
||||
**Validation:**
|
||||
Real-time validation, especially for ZIP/postal code format based on country.
|
||||
|
||||
## Payment Methods
|
||||
|
||||
**Note**: Payment method storage is optional. Only implement if:
|
||||
- Backend securely handles tokenized payment data
|
||||
- PCI DSS compliance requirements are met
|
||||
- Payment gateway supports tokenization (Stripe, Braintree)
|
||||
|
||||
**Security (CRITICAL):**
|
||||
- Never store full card numbers (tokenize with payment gateway)
|
||||
- Display last 4 digits only
|
||||
- Don't store CVV
|
||||
- Use payment gateway hosted forms (Stripe Elements, etc.)
|
||||
- Show "Securely stored" badge for trust
|
||||
|
||||
**Saved payment display:**
|
||||
- Card type logo (Visa, Mastercard)
|
||||
- Last 4 digits
|
||||
- Expiration date
|
||||
- Default indicator
|
||||
- Actions: Edit (update expiration/billing address), Delete, Set as Default
|
||||
|
||||
**Tradeoff**: Saved payment methods increase convenience but require PCI compliance. If not implemented, users enter payment at checkout each time (more friction but simpler backend).
|
||||
|
||||
## Profile and Security
|
||||
|
||||
### Profile Information
|
||||
|
||||
Display and edit customer information.
|
||||
|
||||
**Standard fields:**
|
||||
- Full name
|
||||
- Email (with verification status)
|
||||
- Phone number
|
||||
- Optional: Date of birth, gender
|
||||
|
||||
**Edit functionality:**
|
||||
Inline editing or separate form, real-time validation, success confirmation.
|
||||
|
||||
**Email verification:**
|
||||
If unverified, show warning with "Resend verification email" button. If verified, show checkmark badge.
|
||||
|
||||
### Security Settings
|
||||
|
||||
**Password change:**
|
||||
- Require current password (optional)
|
||||
- New password with strength indicator
|
||||
- Confirm new password
|
||||
- Password requirements display (8+ chars, uppercase, number)
|
||||
|
||||
**Two-factor authentication (optional):**
|
||||
Enable/disable 2FA, setup instructions, backup codes. Only implement if backend supports.
|
||||
|
||||
## Email Preferences
|
||||
|
||||
Ecommerce-specific email controls.
|
||||
|
||||
**Preference categories:**
|
||||
|
||||
1. **Transactional emails** (order updates, shipping) - Recommended always enabled, may be legally required
|
||||
2. **Marketing emails** (sales, promotions, new products) - User choice
|
||||
3. **Newsletter** (weekly roundup, content) - User choice
|
||||
|
||||
**Display:**
|
||||
Checkbox list or toggle switches with clear descriptions. Save button at bottom.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Email Preferences
|
||||
|
||||
[✓] Order and shipping updates
|
||||
Receive confirmations and tracking info
|
||||
|
||||
[ ] Marketing emails
|
||||
Sales, promotions, and new products
|
||||
|
||||
[ ] Newsletter
|
||||
Weekly roundup and articles
|
||||
|
||||
[Save Preferences]
|
||||
```
|
||||
|
||||
**Unsubscribe:**
|
||||
Individual opt-outs per type, "Unsubscribe from all marketing" button. Keep transactional emails enabled (required for order fulfillment).
|
||||
|
||||
## Navigation and Layout
|
||||
|
||||
### Layout Pattern Decision
|
||||
|
||||
Choose based on account complexity:
|
||||
|
||||
**Sidebar Navigation (Recommended):**
|
||||
- **Use when**: 6+ account sections, complex account features
|
||||
- Desktop: Vertical sidebar (20-25% width) with section links
|
||||
- Mobile: Collapse to hamburger menu or dropdown
|
||||
- Benefits: Persistent navigation, professional, accommodates many sections
|
||||
|
||||
**Tab Navigation:**
|
||||
- **Use when**: 4-6 account sections, simpler account structure
|
||||
- Horizontal tabs at top, active tab highlighted
|
||||
- Mobile: Horizontal scroll or dropdown
|
||||
- Benefits: Modern, clean, quick switching
|
||||
|
||||
**Account Hub (Mobile-First):**
|
||||
- **Use when**: Mobile-heavy traffic, simple account
|
||||
- Landing page with section cards (2-column grid)
|
||||
- Tap card to enter section, back button returns to hub
|
||||
- Benefits: Touch-friendly, intuitive, minimal hierarchy
|
||||
|
||||
### Section Organization
|
||||
|
||||
**Recommended order (most to least used):**
|
||||
1. Dashboard (landing page)
|
||||
2. Orders (most accessed)
|
||||
3. Addresses (important for checkout)
|
||||
4. Payment Methods (if implemented)
|
||||
5. Profile
|
||||
6. Security
|
||||
7. Email Preferences
|
||||
8. Logout
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Mobile-specific patterns:**
|
||||
|
||||
**Navigation:**
|
||||
Account hub with section cards (2 columns), or bottom navigation with 4-5 key sections (Orders, Addresses, Profile, More).
|
||||
|
||||
**Forms:**
|
||||
One field per row, larger inputs (48px height), appropriate keyboard types (email, phone, numeric), autofill enabled.
|
||||
|
||||
**Order history:**
|
||||
Simplified order cards, full-width buttons, "Load More" pagination (better than numbered pages on mobile).
|
||||
|
||||
**Saved addresses:**
|
||||
Stacked address cards, full-width, 48px touch targets for edit/delete.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential features:**
|
||||
|
||||
- [ ] Account dashboard with recent orders (3-5)
|
||||
- [ ] Reorder button (adds items to cart, stays on page)
|
||||
- [ ] Order history with status indicators
|
||||
- [ ] Filter orders by date range and status
|
||||
- [ ] Search orders by number or product name
|
||||
- [ ] Order details page with tracking info
|
||||
- [ ] Status timeline (Order Placed → Processing → Shipped → Delivered)
|
||||
- [ ] Track shipment button (links to carrier)
|
||||
- [ ] Download invoice/receipt option
|
||||
- [ ] Saved addresses list with default indicator
|
||||
- [ ] Add/edit/delete addresses with validation
|
||||
- [ ] Set default address option
|
||||
- [ ] Profile information edit
|
||||
- [ ] Email verification status display
|
||||
- [ ] Password change with strength indicator
|
||||
- [ ] Current password required to change password
|
||||
- [ ] Email preferences (transactional vs marketing)
|
||||
- [ ] Account deletion option
|
||||
- [ ] Logout button clearly visible
|
||||
- [ ] Clear navigation between sections
|
||||
- [ ] Mobile-responsive (single column, 48px touch targets)
|
||||
- [ ] Backend integration (all data fetched from API)
|
||||
- [ ] Success confirmations after saves
|
||||
- [ ] Error handling with clear messages
|
||||
- [ ] Keyboard accessible
|
||||
- [ ] ARIA labels on navigation sections
|
||||
- [ ] Order status announcements for screen readers
|
||||
|
||||
**Optional features:**
|
||||
|
||||
- [ ] Saved payment methods (if PCI compliant backend)
|
||||
- [ ] Two-factor authentication
|
||||
- [ ] Wishlist integration
|
||||
- [ ] Loyalty points/rewards display
|
||||
- [ ] Returns management section
|
||||
- [ ] Address autocomplete API
|
||||
@@ -0,0 +1,316 @@
|
||||
# Cart Page
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Layout Patterns](#layout-patterns)
|
||||
- [Cart Items Display](#cart-items-display)
|
||||
- [Quantity Updates](#quantity-updates)
|
||||
- [Order Summary](#order-summary)
|
||||
- [Promo Code Input](#promo-code-input)
|
||||
- [Checkout Button](#checkout-button)
|
||||
- [Empty Cart State](#empty-cart-state)
|
||||
- [Backend Integration](#backend-integration)
|
||||
- [Mobile Cart](#mobile-cart)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
The cart page displays all items a customer has added to their shopping cart. Purpose: Review items, modify cart, apply promotions, proceed to checkout. Critical conversion point.
|
||||
|
||||
**⚠️ CRITICAL: Always display variant details (size, color, material, etc.) for each cart item, not just product titles.**
|
||||
|
||||
### Key Ecommerce Functions
|
||||
|
||||
- Review items before purchase (reduces buyer's remorse)
|
||||
- Update quantities or remove items (cart management)
|
||||
- Apply promotional codes (increase order value)
|
||||
- View pricing breakdown (transparency builds trust)
|
||||
- Proceed to checkout (conversion path)
|
||||
- Continue shopping if needed (reduce abandonment)
|
||||
|
||||
## Layout Patterns
|
||||
|
||||
### Two-Column Pattern (Desktop)
|
||||
|
||||
**Most common:**
|
||||
- Left column (60-70%): Cart items list
|
||||
- Right column (30-40%): Order summary (sticky)
|
||||
- Below items: Promo code input, continue shopping
|
||||
- Order summary stays visible during scroll
|
||||
|
||||
### Mobile Layout
|
||||
|
||||
Single column (stacked):
|
||||
- Cart items
|
||||
- Order summary
|
||||
- Promo code input
|
||||
- Checkout button (sticky at bottom)
|
||||
- Continue shopping
|
||||
|
||||
## Cart Items Display
|
||||
|
||||
### Cart Item Card
|
||||
|
||||
**CRITICAL: Always display variant details for each cart item.**
|
||||
|
||||
Products with variants (size, color, material, style, etc.) must show the selected variant options. Without this, customers can't confirm they have the correct items in their cart.
|
||||
|
||||
**Essential information per item:**
|
||||
- Product image (thumbnail, 80-120px desktop, 60-80px mobile)
|
||||
- Product title (linked to product page)
|
||||
- **Variant details (REQUIRED)**: Size, color, material, or other variant options selected
|
||||
- Format: "Size: Large, Color: Black" or "Large / Black"
|
||||
- Display below title, smaller gray text
|
||||
- Show ALL selected variant options
|
||||
- Unit price
|
||||
- Quantity selector
|
||||
- Line total (unit price × quantity)
|
||||
- Remove button (X icon)
|
||||
|
||||
**Layout:**
|
||||
Horizontal card (image left, details right), clear visual separation between items, adequate spacing (16-24px).
|
||||
|
||||
**Why variant details are critical:**
|
||||
- Customer confirmation before checkout
|
||||
- Prevents returns from wrong variant purchases
|
||||
- Allows easy correction if wrong variant in cart
|
||||
- Essential for clothing, shoes, configurable products
|
||||
|
||||
### Price Display
|
||||
|
||||
**Medusa pricing (CRITICAL):**
|
||||
Medusa stores prices as-is (not in cents). Display prices directly without dividing by 100. Example: If Medusa returns 49.99, display $49.99 (not $0.4999). Different from Stripe which stores prices in cents.
|
||||
|
||||
**Sale prices:**
|
||||
Show original price (strikethrough) and sale price prominently if on sale.
|
||||
|
||||
**Line total:**
|
||||
Total for item (price × quantity), bold or larger font, update dynamically when quantity changes.
|
||||
|
||||
## Quantity Updates
|
||||
|
||||
### Quantity Selector
|
||||
|
||||
Standard +/- buttons with number display:
|
||||
```
|
||||
[-] [2] [+]
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- Min: 1 (can't go below, or remove item instead)
|
||||
- Max: Stock available or cart limit
|
||||
- Manual input allowed (type number)
|
||||
- Update on change (blur or button click)
|
||||
- Show loading state briefly
|
||||
- Update line total immediately
|
||||
|
||||
### Auto-Update (Recommended)
|
||||
|
||||
Changes apply immediately, no "Update Cart" button needed. Better UX, less friction. Show brief loading indicator. Update order summary automatically.
|
||||
|
||||
**Error handling:**
|
||||
"Only X available" if exceeds stock, reset to max available quantity, show error message near item.
|
||||
|
||||
## Order Summary
|
||||
|
||||
### Summary Card
|
||||
|
||||
Position: Right column on desktop (sticky), below cart items on mobile, fixed width (300-400px desktop).
|
||||
|
||||
### Price Breakdown
|
||||
|
||||
**Line items:**
|
||||
```
|
||||
Subtotal (3 items): $149.97
|
||||
Shipping: $9.99
|
||||
Tax: $12.00
|
||||
─────────────────────
|
||||
Total: $171.96
|
||||
```
|
||||
|
||||
**Subtotal:**
|
||||
Sum of all cart items with item count.
|
||||
|
||||
**Shipping:**
|
||||
Estimated shipping cost, or "Calculated at checkout" (if address needed), or "Free shipping" (if applicable). Show free shipping threshold progress (see promotions.md).
|
||||
|
||||
**Tax:**
|
||||
Estimated tax or "Calculated at checkout" (if address needed).
|
||||
|
||||
**Total:**
|
||||
Grand total (bold, larger font), most prominent number.
|
||||
|
||||
### Savings Display
|
||||
|
||||
If discounts applied:
|
||||
- Show total savings: "You saved $20.00" (green text)
|
||||
- Or: Discount line item in breakdown
|
||||
- Positive reinforcement
|
||||
|
||||
## Promo Code Input
|
||||
|
||||
### Input Field Design
|
||||
|
||||
**Layout:**
|
||||
Label ("Promo code" or "Discount code"), text input (200-280px desktop, full-width mobile), "Apply" button inline or stacked (mobile). Positioned below cart items or in order summary.
|
||||
|
||||
**Auto-uppercase:**
|
||||
On submit (codes usually uppercase).
|
||||
|
||||
**Expandable pattern (optional):**
|
||||
"Have a promo code?" link that expands to show input. Saves vertical space.
|
||||
|
||||
### Success and Error States
|
||||
|
||||
**Success:**
|
||||
- Green checkmark or success message: "Code applied: WELCOME10"
|
||||
- Discount shown in order summary: "Discount (WELCOME10) -$10.00"
|
||||
- Remove option: X icon or "Remove" link
|
||||
- Update cart total immediately
|
||||
|
||||
**Error:**
|
||||
- Red error message below input: "Invalid code", "Code expired", or "Minimum purchase not met"
|
||||
- Input remains visible for retry
|
||||
- Don't clear input field
|
||||
|
||||
**See also:** [promotions.md](../features/promotions.md) for detailed promo code patterns.
|
||||
|
||||
## Checkout Button
|
||||
|
||||
### Button Design
|
||||
|
||||
**Prominence:**
|
||||
Large, full-width button, brand primary color (high contrast), 48-56px height (easy to tap). Text: "Proceed to Checkout" or "Checkout". Icon optional (lock or arrow).
|
||||
|
||||
**Position:**
|
||||
Bottom of order summary (desktop), fixed at bottom of screen (mobile, optional), always visible during scroll.
|
||||
|
||||
**States:**
|
||||
Default enabled, hover with slight color change, loading with spinner, disabled if cart empty or error.
|
||||
|
||||
**Security Indicators (optional):**
|
||||
Lock icon with "Secure Checkout", payment badges (Visa, Mastercard, PayPal), "SSL Encrypted" message near button.
|
||||
|
||||
## Empty Cart State
|
||||
|
||||
### Display
|
||||
|
||||
When cart is empty:
|
||||
- Centered content
|
||||
- Icon or illustration (empty shopping bag)
|
||||
- Heading: "Your cart is empty"
|
||||
- Subtext: "Start adding items to your cart"
|
||||
- CTA button: "Continue Shopping" or "Browse Products"
|
||||
|
||||
**Additional elements:**
|
||||
- Link to popular categories
|
||||
- Recently viewed products (if available)
|
||||
- Bestsellers or featured products
|
||||
|
||||
## Backend Integration
|
||||
|
||||
### Data Source (CRITICAL)
|
||||
|
||||
**Fetch from ecommerce backend:**
|
||||
Cart stored in backend (persistent), fetch on page load, sync with backend on changes.
|
||||
|
||||
**When to fetch:**
|
||||
- Page load (initial cart data)
|
||||
- After adding/updating/removing items
|
||||
- After applying promo codes
|
||||
|
||||
### State Management
|
||||
|
||||
**Client-side cart state:**
|
||||
Store cart data in global state (React Context), keep cart ID in localStorage, update state after API responses, share cart state across components (page, popup, header badge).
|
||||
|
||||
**Cart ID persistence:**
|
||||
```javascript
|
||||
localStorage.setItem('cart_id', cartId)
|
||||
```
|
||||
|
||||
Send cart ID with every cart API request, create new cart if ID doesn't exist, clear cart ID on checkout completion.
|
||||
|
||||
### TanStack Query for Cart Data
|
||||
|
||||
**Recommended** for efficient caching and revalidation:
|
||||
|
||||
**Benefits:**
|
||||
Built-in caching with automatic revalidation, optimistic updates support, automatic refetching on focus/reconnect, loading and error states handled, query invalidation for cart updates.
|
||||
|
||||
**Configuration:**
|
||||
Use `useQuery` for fetching cart data, set `staleTime` to 30-60 seconds, use `queryClient.invalidateQueries(['cart'])` after updates.
|
||||
|
||||
**See also:** [connecting-to-backend.md](../connecting-to-backend.md) for detailed backend integration patterns.
|
||||
|
||||
### Medusa Integration
|
||||
|
||||
Use `@medusajs/medusa-js` SDK:
|
||||
- Cart endpoints: `/store/carts`, `/store/carts/{id}`
|
||||
- Add to cart: POST `/store/carts/{id}/line-items`
|
||||
- Update quantity: POST `/store/carts/{id}/line-items/{lineId}`
|
||||
- Remove item: DELETE `/store/carts/{id}/line-items/{lineId}`
|
||||
- Apply discount: POST `/store/carts/{id}/promotions`
|
||||
|
||||
**Response data:**
|
||||
Cart ID, items (product details, variants, quantities), subtotal, tax, shipping, total, applied discounts, item availability status.
|
||||
|
||||
**Error handling:**
|
||||
Network errors (show retry option), invalid cart ID (create new cart), out of stock (show error, prevent adding), API errors (user-friendly message).
|
||||
|
||||
## Mobile Cart
|
||||
|
||||
### Mobile Layout
|
||||
|
||||
**Structure:**
|
||||
Full-width cart items (stacked), simplified item cards, order summary below items, sticky checkout button at bottom.
|
||||
|
||||
**Cart item cards:**
|
||||
Smaller product images (60-80px), truncated product titles (1-2 lines), essential info only, quantity selector (smaller, 36-40px), remove button visible.
|
||||
|
||||
### Sticky Checkout Bar
|
||||
|
||||
**Bottom sticky bar:**
|
||||
Fixed at bottom of screen, total amount visible, "Checkout" button (full-width), appears after scrolling (optional), always accessible.
|
||||
|
||||
**Design:**
|
||||
```
|
||||
[Total: $171.96] [Checkout]
|
||||
```
|
||||
|
||||
**Touch-friendly:**
|
||||
44px minimum touch targets, adequate spacing between buttons, large remove buttons (40px).
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential elements:**
|
||||
|
||||
- [ ] **CRITICAL: Cart items display variant details (size, color, etc.) - not just product title**
|
||||
- [ ] Cart items with images, titles, variant options, prices
|
||||
- [ ] Quantity selector (+/- buttons, 40-44px minimum)
|
||||
- [ ] Remove button per item (X icon, clearly visible)
|
||||
- [ ] Order summary (subtotal, shipping, tax, total)
|
||||
- [ ] Promo code input with "Apply" button
|
||||
- [ ] Applied discount displayed in summary
|
||||
- [ ] "Remove" option for applied code
|
||||
- [ ] Prominent "Checkout" button (48-56px height)
|
||||
- [ ] Continue shopping link
|
||||
- [ ] Empty cart state (icon, message, CTA)
|
||||
- [ ] Trust signals (secure checkout, payment badges)
|
||||
- [ ] Auto-update quantities (no "Update Cart" button)
|
||||
- [ ] Undo option after removing item (toast notification)
|
||||
- [ ] Mobile: Sticky checkout button at bottom
|
||||
- [ ] Mobile: Simplified cart item cards
|
||||
- [ ] Backend integration (fetch cart from API)
|
||||
- [ ] Cart ID persistence (localStorage)
|
||||
- [ ] Real-time price updates
|
||||
- [ ] Loading states (skeleton or spinner)
|
||||
- [ ] Optimistic updates for quantity changes
|
||||
- [ ] Stock availability warnings (if low stock)
|
||||
- [ ] Free shipping threshold progress (if applicable)
|
||||
- [ ] Keyboard accessible (Tab, Enter, Arrow keys)
|
||||
- [ ] ARIA labels on quantity controls and buttons
|
||||
- [ ] Screen reader announcements (aria-live)
|
||||
- [ ] High contrast text (4.5:1 minimum)
|
||||
- [ ] Error handling for failed updates
|
||||
@@ -0,0 +1,486 @@
|
||||
# Checkout Page Layout
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Decision: Single-Page vs Multi-Step](#decision-single-page-vs-multi-step)
|
||||
- [Guest vs Logged-In Checkout](#guest-vs-logged-in-checkout)
|
||||
- [Component Architecture](#component-architecture-recommended)
|
||||
- [Checkout Flow](#checkout-flow)
|
||||
- [Key Ecommerce Considerations](#key-ecommerce-considerations)
|
||||
- [Backend Integration](#backend-integration)
|
||||
- [Mobile Checkout](#mobile-checkout)
|
||||
- [Trust and Conversion Optimization](#trust-and-conversion-optimization)
|
||||
- [Error Handling](#error-handling)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Final step in conversion funnel where customers provide shipping and payment information. Must be optimized for completion with minimal friction.
|
||||
|
||||
**⚠️ CRITICAL: Always fetch shipping methods AND payment methods from backend. Users must be able to select from available options - never skip payment method selection.**
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Clear steps and progress indication
|
||||
- Guest checkout option (if backend supports it)
|
||||
- Shipping address and method selection
|
||||
- **Shipping methods fetched from backend (vary by address/region)**
|
||||
- **Payment methods fetched from backend (user must select preferred method)**
|
||||
- Payment processing
|
||||
- Order review before submission
|
||||
- Trust signals throughout
|
||||
- Mobile-optimized (60%+ traffic is mobile)
|
||||
- Fast loading and submission
|
||||
|
||||
## Decision: Single-Page vs Multi-Step
|
||||
|
||||
**Use Single-Page Checkout when:**
|
||||
- Simple products with few shipping options
|
||||
- Mobile-heavy traffic (>60% mobile users)
|
||||
- Fewer form fields required (<15 total)
|
||||
- Startup or new store (minimize friction)
|
||||
- Fast checkout is prioritized
|
||||
- Low average order value (<$50)
|
||||
|
||||
**Benefits:**
|
||||
- Fewer clicks (no step navigation)
|
||||
- User sees full scope upfront
|
||||
- Faster on mobile (no page loads)
|
||||
- Lower perceived friction
|
||||
|
||||
**Use Multi-Step Checkout when:**
|
||||
- Complex shipping (international, multiple carriers)
|
||||
- B2B customers (need detailed information)
|
||||
- Many form fields required (>15 total)
|
||||
- High-value products (>$100, thoroughness expected)
|
||||
- Established brand (customers trust process)
|
||||
- Need clear progress indication
|
||||
|
||||
**Benefits:**
|
||||
- Less overwhelming (one step at a time)
|
||||
- Progress indicator reduces anxiety
|
||||
- Easier step-by-step validation
|
||||
- Better for complex forms
|
||||
|
||||
**Recommended: Hybrid Approach**
|
||||
- Single-page scroll layout on desktop
|
||||
- Accordion-based sections on mobile (expand/collapse)
|
||||
- Progressive disclosure of sections
|
||||
- Best of both worlds
|
||||
|
||||
**Common steps:**
|
||||
1. Shipping Information (address)
|
||||
2. Delivery (shipping method selection)
|
||||
3. Payment (payment method and details)
|
||||
4. Review (final review before submission)
|
||||
|
||||
## Guest vs Logged-In Checkout
|
||||
|
||||
**IMPORTANT:** Guest checkout availability depends on backend support.
|
||||
|
||||
**Guest checkout (recommended if backend supports it):**
|
||||
- Reduces friction (no signup barrier)
|
||||
- "Checkout as Guest" option prominent
|
||||
- Email required for order confirmation
|
||||
- Optional "Create account?" checkbox after order
|
||||
- Don't force account creation
|
||||
|
||||
**Logged-in checkout:**
|
||||
- Pre-fill saved addresses and payment methods
|
||||
- "Returning customer? Log in" link at top
|
||||
- Allow seamless switch between guest/login
|
||||
|
||||
## Component Architecture (RECOMMENDED)
|
||||
|
||||
**Build separate components for each checkout step for better maintainability and reusability.**
|
||||
|
||||
✅ **Create individual step components:**
|
||||
- `ShippingInformationStep` - Contact and shipping address form
|
||||
- `DeliveryMethodStep` - Shipping method selection
|
||||
- `PaymentInformationStep` - Payment method and details
|
||||
- `OrderReviewStep` - Final review before submission
|
||||
|
||||
**Benefits of component separation:**
|
||||
- **Maintainability**: Fix bugs or update one step without affecting others
|
||||
- **Reusability**: Reuse shipping address component in account settings, checkout, etc.
|
||||
- **Testability**: Test each step independently
|
||||
- **Code organization**: Clearer separation of concerns (validation, submission logic per step)
|
||||
- **Easier debugging**: Isolate issues to specific steps
|
||||
- **Flexibility**: Easy to reorder steps or add/remove steps based on requirements
|
||||
- **Performance**: Lazy load steps or split bundles for faster initial load
|
||||
|
||||
**What to separate:**
|
||||
- Main checkout page/container component
|
||||
- Individual step components (ShippingInformationStep, DeliveryMethodStep, etc.)
|
||||
- Reusable order summary component (shown on all steps)
|
||||
|
||||
**Component communication:**
|
||||
Each step component should accept:
|
||||
- Current step data (form values)
|
||||
- Callback to update data (e.g., `onShippingUpdate`)
|
||||
- Callback to proceed to next step (e.g., `onContinue`)
|
||||
- Loading/error states
|
||||
- Validation errors
|
||||
|
||||
**Shared components:**
|
||||
- Address form (used in shipping and billing)
|
||||
- Payment method selector
|
||||
- Order summary (sidebar, shown on all steps)
|
||||
|
||||
**Works for both single-page and multi-step:**
|
||||
- Single-page: Render all steps at once, scroll-based navigation
|
||||
- Multi-step: Show one component at a time, controlled by step state
|
||||
- Accordion: Expand/collapse components as sections
|
||||
|
||||
**Common mistake:**
|
||||
- ❌ Building entire checkout as one massive component with all form fields, logic, and validation mixed together
|
||||
- ✅ Separate components for each step, shared state management in parent
|
||||
|
||||
## Checkout Flow
|
||||
|
||||
### Complete Checkout Flow Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ CHECKOUT PROCESS │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Optional: Guest Checkout vs Login │
|
||||
│ • Guest: Enter email only │
|
||||
│ • Logged-in: Pre-fill saved data │
|
||||
└────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ STEP 1: Shipping Information │
|
||||
│ ├─ Contact: Email, Phone │
|
||||
│ ├─ Shipping Address: Name, Address, City, etc. │
|
||||
│ └─ Billing Address: □ Same as shipping / Different │
|
||||
└────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ STEP 2: Delivery │
|
||||
│ • Fetch shipping methods from backend │
|
||||
│ • Display: Standard, Express, Overnight │
|
||||
│ • Show: Cost + Delivery estimate │
|
||||
│ • Update order total │
|
||||
└────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ STEP 3: Payment Information │
|
||||
│ • Fetch payment methods from backend │
|
||||
│ • Options: Card, PayPal, Apple Pay, etc. │
|
||||
│ • Enter: Card details (tokenized) │
|
||||
│ • Use billing address from Step 1 │
|
||||
└────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ STEP 4: Order Review │
|
||||
│ • Review: Items, addresses, shipping, payment │
|
||||
│ • Optional: □ Agree to Terms and Conditions │
|
||||
│ • Click: [Place Order] Button │
|
||||
│ → Payment processing triggered │
|
||||
└────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Loading: Processing payment... │
|
||||
│ • Authorize/capture payment via gateway │
|
||||
│ • Create order in backend │
|
||||
│ • Send confirmation email │
|
||||
└────────────────────┬─────────────────────────────────┘
|
||||
│
|
||||
┌────┴────┐
|
||||
│ │
|
||||
Success Failure
|
||||
│ │
|
||||
▼ ▼
|
||||
┌───────────────────┐ ┌──────────────────────┐
|
||||
│ Order Confirmation│ │ Show Error Message │
|
||||
│ • Order number │ │ • Retry payment │
|
||||
│ • Details │ │ • Keep form data │
|
||||
│ • Tracking link │ │ • Suggest solutions │
|
||||
└───────────────────┘ └──────────────────────┘
|
||||
```
|
||||
|
||||
## Key Ecommerce Considerations
|
||||
|
||||
### Shipping Address Collection
|
||||
|
||||
Collect:
|
||||
- Required: email, name, address, city, state/zip, country
|
||||
- Optional: phone.
|
||||
|
||||
**Key ecommerce considerations:**
|
||||
- Email placement: First if guest checkout (identifies customer)
|
||||
- Country placement: Early if shipping methods vary by country (affects available shipping)
|
||||
- Phone: Optional to reduce friction, but recommended for delivery coordination
|
||||
- Billing address: "Same as shipping" checkbox (default checked)
|
||||
|
||||
**For Medusa backends:**
|
||||
- Country dropdown: Show only countries from cart's region (don't show all countries globally)
|
||||
- Get countries from: `cart.region.countries` or `sdk.store.region.retrieve(cart.region_id)`
|
||||
- Medusa regions contain specific countries - limiting options ensures correct pricing and shipping
|
||||
- If user needs different country, they must change region first (typically via country selector component)
|
||||
|
||||
### Shipping Method Selection
|
||||
|
||||
**Fetch from backend after address provided** (shipping methods vary by address/region):
|
||||
- Display as radio buttons with cost + delivery estimate
|
||||
- Update order total immediately when method changes
|
||||
- Highlight free shipping if available
|
||||
- Show "Add $X for free shipping" if close to threshold
|
||||
- Handle unavailable shipping: show message, suggest alternatives
|
||||
|
||||
### Payment Method Selection
|
||||
|
||||
**CRITICAL: Always fetch payment methods from backend and allow user to select from available options.**
|
||||
|
||||
Payment methods vary by store configuration (backend settings). NEVER assume which payment methods are available or hardcode payment options. Users MUST be able to choose their preferred payment method.
|
||||
|
||||
**Fetch available methods from backend:**
|
||||
```typescript
|
||||
// ALWAYS fetch payment providers from backend
|
||||
// For Medusa:
|
||||
const { payment_providers } = await sdk.store.payment.listPaymentProviders()
|
||||
|
||||
// For other backends:
|
||||
// Change based on the integrated backend
|
||||
const paymentMethods = await fetch(`${apiUrl}/payment-methods`)
|
||||
// Returns: card, paypal, apple_pay, google_pay, stripe, etc.
|
||||
```
|
||||
|
||||
**Display payment method selection UI:**
|
||||
- Show all enabled payment providers returned by backend
|
||||
- Allow user to select their preferred method (radio buttons or cards)
|
||||
- Don't skip selection step - user must actively choose
|
||||
- Map backend codes to display names in the storefront. For example `pp_system_manual` -> `Manual payment`.
|
||||
- Common options: Credit/Debit Card, PayPal, Apple Pay, Google Pay, Buy Now Pay Later
|
||||
|
||||
**Available payment methods (examples, actual options come from backend):**
|
||||
- Credit/Debit Card (most common, via Stripe/Braintree/other gateway)
|
||||
- PayPal (redirect or in-context)
|
||||
- Apple Pay (Safari, iOS only)
|
||||
- Google Pay (Chrome, Android)
|
||||
- Buy Now Pay Later (Affirm, Klarna - if enabled by store)
|
||||
- Manual payment (bank transfer, cash on delivery - if enabled)
|
||||
|
||||
**Why backend fetching is required:**
|
||||
- Store admin controls which payment providers are enabled
|
||||
- Payment methods vary by region, currency, order value
|
||||
- Test vs production mode affects available methods
|
||||
- Can't assume all stores use the same payment gateway
|
||||
|
||||
**For Medusa backends - Payment flow:**
|
||||
|
||||
1. **List available payment providers:**
|
||||
```typescript
|
||||
const { payment_providers } = await sdk.store.payment.listPaymentProviders({
|
||||
region_id: cart.region_id // Required to get region-specific providers
|
||||
})
|
||||
```
|
||||
|
||||
2. **Display providers and allow user to select:**
|
||||
Show payment providers as radio buttons or cards. User must actively select one.
|
||||
|
||||
3. **Initialize payment session after selection:**
|
||||
```typescript
|
||||
// When user selects a provider
|
||||
await sdk.store.payment.initiatePaymentSession(cart, {
|
||||
provider_id: selectedProvider.id // e.g., "pp_stripe_stripe", "pp_system_default"
|
||||
})
|
||||
|
||||
// Re-fetch cart to get updated payment session data
|
||||
const { cart: updatedCart } = await sdk.store.cart.retrieve(cart.id)
|
||||
```
|
||||
|
||||
4. **Render provider-specific UI:**
|
||||
- Stripe providers (`pp_stripe_*`): Render Stripe Elements card UI
|
||||
- Manual payment (`pp_system_default`): No additional UI needed
|
||||
- Other providers: Implement according to provider requirements
|
||||
|
||||
**Important:** Payment provider IDs are returned from the backend (e.g., `pp_stripe_stripe`, `pp_system_manual`). Map these to user-friendly display names in your UI.
|
||||
|
||||
**Digital wallets (mobile priority):**
|
||||
- Apple Pay / Google Pay should be prominent on mobile
|
||||
- One-click payment (pre-filled shipping)
|
||||
- Significantly faster checkout
|
||||
- Higher conversion on mobile
|
||||
|
||||
**Card payment:**
|
||||
- Use payment gateway (Stripe Elements, Braintree)
|
||||
- Never handle raw card data (PCI compliance)
|
||||
- Tokenize card data before submission
|
||||
- Auto-detect card type (show logo)
|
||||
|
||||
### Order Review
|
||||
|
||||
**Display for final confirmation:**
|
||||
Cart items, addresses, shipping method/cost, payment method, order total breakdown.
|
||||
|
||||
**Key elements:**
|
||||
- "Edit" link next to each section (returns to step or edits inline)
|
||||
- Terms checkbox (if required): "I agree to Terms and Conditions"
|
||||
- Place Order button: Large (48-56px), shows total, loading state on submit
|
||||
|
||||
### Order Summary Sidebar
|
||||
|
||||
**Desktop:** Sticky sidebar with items, prices, totals. Updates in real-time.
|
||||
**Mobile:** Collapsible at top ("Show order summary" toggle). Keeps focus on form.
|
||||
|
||||
## Backend Integration
|
||||
|
||||
**Address validation (optional):**
|
||||
- Use address lookup APIs (Google, SmartyStreets) for higher accuracy
|
||||
- Tradeoff: accuracy vs friction. Consider for high-value orders.
|
||||
|
||||
**Payment processing flow:**
|
||||
1. Frontend tokenizes payment (Stripe Elements, Braintree)
|
||||
2. Send token + order details to backend
|
||||
3. Backend authorizes/captures payment & creates order
|
||||
4. Redirect to confirmation page
|
||||
|
||||
**Never:** Send raw card data, store cards without PCI compliance, process payments client-side.
|
||||
|
||||
**On payment failure:** Show specific error, keep form data, allow retry without re-entering.
|
||||
|
||||
### Order Completion and Cart Cleanup (CRITICAL)
|
||||
|
||||
**After order is successfully placed, you MUST reset the cart state:**
|
||||
|
||||
**Common issue:** Cart popup and cart state still show old cart content after order is placed. This happens because the global cart state (Context, Zustand, Redux) isn't cleared after checkout completion.
|
||||
|
||||
**Required actions on successful order:**
|
||||
|
||||
1. **Clear cart from global state:**
|
||||
- Reset cart state in Context/Zustand/Redux to null or empty
|
||||
- Update cart count to 0 in navbar
|
||||
- Prevent old cart items from showing in cart popup
|
||||
|
||||
2. **Clear localStorage cart ID:**
|
||||
- Remove cart ID from localStorage: `localStorage.removeItem('cart_id')`
|
||||
- Or create new cart and update cart ID in localStorage
|
||||
- Ensures fresh cart for next shopping session
|
||||
|
||||
3. **Invalidate cart queries (if using TanStack Query):**
|
||||
- `queryClient.invalidateQueries({ queryKey: ['cart'] })`
|
||||
- Or `queryClient.removeQueries({ queryKey: ['cart', cartId] })`
|
||||
- Prevents stale cart data from cache
|
||||
|
||||
4. **Redirect to order confirmation page:**
|
||||
- Navigate to `/order-confirmation/[order_id]` or `/thank-you/[order_id]`
|
||||
- Show order details, tracking info, confirmation
|
||||
|
||||
**Pattern:**
|
||||
```typescript
|
||||
// After successful order placement
|
||||
async function onOrderSuccess(order) {
|
||||
// 1. Clear cart state
|
||||
setCart(null) // or clearCart() from context
|
||||
|
||||
// 2. Clear localStorage
|
||||
localStorage.removeItem('cart_id')
|
||||
|
||||
// 3. Invalidate queries (if using TanStack Query)
|
||||
queryClient.invalidateQueries({ queryKey: ['cart'] })
|
||||
|
||||
// 4. Redirect to confirmation
|
||||
router.push(`/order-confirmation/${order.id}`)
|
||||
}
|
||||
```
|
||||
|
||||
**Why this is critical:**
|
||||
- Without clearing cart state, cart popup shows old items after order
|
||||
- User sees "phantom cart" if they click cart icon after checkout
|
||||
- Creates confusion and poor UX
|
||||
- May prevent user from starting new shopping session
|
||||
|
||||
## Mobile Checkout
|
||||
|
||||
**Key optimizations:**
|
||||
- Digital wallets prominent (Apple Pay/Google Pay) - significantly faster checkout
|
||||
- Single-column layout, 44-48px touch targets
|
||||
- Appropriate keyboard types, autocomplete attributes enabled
|
||||
- Collapsible order summary at top (shows total, expands on tap)
|
||||
- Sticky Place Order button at bottom (always accessible, shows total)
|
||||
- Accordion sections (one step at a time, reduces cognitive load)
|
||||
|
||||
**For detailed mobile patterns and safe area insets**, see `reference/mobile-responsiveness.md`.
|
||||
|
||||
## Trust and Conversion Optimization
|
||||
|
||||
**Trust signals (critical for conversion):**
|
||||
- "Secure Checkout" badge, payment provider logos (Visa, Mastercard)
|
||||
- Return policy link visible, customer support contact
|
||||
- Near Place Order: "100% secure checkout", guarantees/free returns if offered
|
||||
- For new brands: Customer review count, social proof
|
||||
|
||||
**Reduce abandonment:**
|
||||
- Progress indicator (shows steps remaining)
|
||||
- Auto-save form data, clear pricing (no surprise fees)
|
||||
- Minimal required fields, smart defaults, autocomplete enabled
|
||||
|
||||
**Reduce perceived friction:**
|
||||
- "No account required" (guest checkout)
|
||||
- "Free shipping" highlighted
|
||||
- Time estimate: "Less than 2 minutes"
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Form validation:**
|
||||
- Validate on blur, show error below field
|
||||
- User-friendly messages ("Please enter a valid email address")
|
||||
- Scroll to first error on submit
|
||||
|
||||
**Payment errors:**
|
||||
- Card declined: "Your card was declined. Please try another payment method."
|
||||
- Keep form data, suggest alternatives (try another card, PayPal)
|
||||
- Network timeout: Show retry option without re-entering data
|
||||
|
||||
**Stock availability errors:**
|
||||
- Out of stock: Remove item, recalculate, allow continue with remaining items
|
||||
- Quantity reduced: Update automatically, show message, allow continue
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential checkout features:**
|
||||
|
||||
- [ ] **RECOMMENDED: Separate components created for each checkout step**
|
||||
- [ ] Components: ShippingInformationStep, DeliveryMethodStep, PaymentInformationStep, OrderReviewStep
|
||||
- [ ] Decision made: Single-page or multi-step (based on complexity)
|
||||
- [ ] Guest checkout option (if backend supports it)
|
||||
- [ ] Email field first (if guest checkout)
|
||||
- [ ] Shipping address form with autocomplete attributes
|
||||
- [ ] "Billing same as shipping" checkbox (default checked)
|
||||
- [ ] Shipping methods fetched from backend dynamically
|
||||
- [ ] Shipping cost updates order total in real-time
|
||||
- [ ] **CRITICAL: Payment methods fetched from backend (NEVER assume or hardcode)**
|
||||
- [ ] **CRITICAL: Payment method selection UI shown to user (user must select from available options)**
|
||||
- [ ] Payment methods: show only enabled providers returned by backend
|
||||
- [ ] For Medusa: Payment session initialized after user selects provider (sdk.store.payment.initiatePaymentSession)
|
||||
- [ ] For Medusa: Country dropdown limited to cart's region countries
|
||||
- [ ] Digital wallets prominent on mobile (Apple Pay, Google Pay)
|
||||
- [ ] Payment tokenization (never send raw card data)
|
||||
- [ ] Order review section before submission
|
||||
- [ ] Order summary sidebar (sticky on desktop, collapsible on mobile)
|
||||
- [ ] Promo code input (if not applied in cart)
|
||||
- [ ] Trust signals throughout (secure checkout, return policy)
|
||||
- [ ] Terms and conditions checkbox (if required)
|
||||
- [ ] Place Order button prominent (48-56px, shows total)
|
||||
- [ ] Loading state during payment processing
|
||||
- [ ] Progress indicator (if multi-step)
|
||||
- [ ] Clear error messages for validation failures
|
||||
- [ ] Error handling for payment failures (keep form data)
|
||||
- [ ] Stock availability check before order creation
|
||||
- [ ] Mobile optimized (44-48px touch targets, single column)
|
||||
- [ ] Autocomplete enabled on all form fields
|
||||
- [ ] Keyboard accessible (tab through fields, enter to submit)
|
||||
- [ ] ARIA labels on form fields (aria-required, aria-invalid)
|
||||
- [ ] Redirect to order confirmation on success
|
||||
- [ ] **CRITICAL: Clear cart state after successful order** (reset cart in Context/Zustand, remove cart ID from localStorage, invalidate cart queries)
|
||||
- [ ] Cart popup shows empty cart after order completion (not old items)
|
||||
@@ -0,0 +1,264 @@
|
||||
# Homepage Layout
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Essential Homepage Sections](#essential-homepage-sections)
|
||||
- [Hero Section](#hero-section)
|
||||
- [Featured Categories](#featured-categories)
|
||||
- [Product Sections](#product-sections)
|
||||
- [Value Propositions](#value-propositions)
|
||||
- [Newsletter Signup](#newsletter-signup)
|
||||
- [Content Hierarchy](#content-hierarchy)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
The homepage is the primary landing page for an ecommerce store. Purpose: Strong first impression, guide users to products, communicate value, drive conversions.
|
||||
|
||||
**Backend Integration (CRITICAL):**
|
||||
|
||||
All content (categories, products, promotions) must be fetched from the ecommerce backend. Do this based on backend integrated. Never hardcode homepage content. Fetch featured products, bestsellers, new arrivals, and categories dynamically.
|
||||
|
||||
### Key Ecommerce Functions
|
||||
|
||||
- Create strong first impression (builds trust)
|
||||
- Guide users to products they want (reduce bounce rate)
|
||||
- Showcase featured products and promotions (increase conversion)
|
||||
- Communicate value propositions (free shipping, returns)
|
||||
- Capture email addresses (build marketing list)
|
||||
- Drive conversions and sales
|
||||
|
||||
## Essential Homepage Sections
|
||||
|
||||
### Must-Have Sections
|
||||
|
||||
**Critical for every homepage:**
|
||||
1. Hero section (above the fold)
|
||||
2. Category navigation (product discovery)
|
||||
3. Featured/bestselling products (social proof)
|
||||
4. Footer (contact, legal, navigation)
|
||||
|
||||
**Strongly recommended:**
|
||||
1. Value propositions (free shipping, returns, etc.)
|
||||
2. Social proof (reviews, testimonials, trust badges)
|
||||
3. New arrivals or sale section
|
||||
4. Newsletter signup
|
||||
|
||||
### Content Hierarchy Decision
|
||||
|
||||
**Above the fold (first screen):**
|
||||
- Hero section with main message
|
||||
- Primary call-to-action
|
||||
- Key value propositions (optional)
|
||||
|
||||
**Middle sections:**
|
||||
- Featured categories
|
||||
- Product sections (bestsellers, new arrivals, sale)
|
||||
- Promotional banners
|
||||
- Social proof
|
||||
|
||||
**Bottom sections:**
|
||||
- Newsletter signup
|
||||
- Footer
|
||||
|
||||
## Hero Section
|
||||
|
||||
Large banner at top of homepage, first thing users see (above the fold). Communicates main message or promotion.
|
||||
|
||||
**Content options:**
|
||||
- Seasonal campaign or sale
|
||||
- New product arrivals
|
||||
- Brand message or value proposition
|
||||
- Featured product category
|
||||
- Multiple rotating slides (carousel) - max 3-4 slides
|
||||
|
||||
**See also:** [hero.md](../components/hero.md) for detailed hero section guidelines including carousel patterns, mobile optimization, and performance.
|
||||
|
||||
## Featured Categories
|
||||
|
||||
### Purpose and Display
|
||||
|
||||
**Purpose**: Help users browse by category, reduce clicks to reach products, quick access to main product types.
|
||||
|
||||
**Category selection:**
|
||||
- 4-8 main categories
|
||||
- Most popular or seasonal categories
|
||||
- Balanced representation
|
||||
- **Fetch from backend dynamically** (never hardcode)
|
||||
|
||||
### Display Patterns
|
||||
|
||||
**Pattern 1: Category Grid with Images**
|
||||
3-6 category tiles with images, category name overlay, click to navigate. Equal-sized tiles in grid layout (3-4 columns desktop, 2 mobile).
|
||||
|
||||
**Pattern 2: Category Cards**
|
||||
Card layout with category image, name, and item count ("120 products"). "Shop [Category]" button on each card. 2-4 columns on desktop, 2 on mobile.
|
||||
|
||||
**Pattern 3: Category Slider**
|
||||
Horizontal scrollable categories showing 4-6 at once. Arrows for navigation. See [product-slider.md](../components/product-slider.md).
|
||||
|
||||
## Product Sections
|
||||
|
||||
### Bestsellers Section (CRITICAL)
|
||||
|
||||
**Purpose**: Showcase popular products, build social proof, guide uncertain shoppers.
|
||||
|
||||
**Product selection (backend-driven):**
|
||||
- Sort by total sales volume
|
||||
- Update regularly (weekly or monthly)
|
||||
- Mix of categories (not all one type)
|
||||
- Show 8-15 products
|
||||
|
||||
**Layout:**
|
||||
Product slider or grid, product cards with image, title, price, rating (if available). "View All" link to full bestsellers page.
|
||||
|
||||
### New Arrivals Section
|
||||
|
||||
**Purpose**: Highlight latest products, create sense of freshness, encourage repeat visits.
|
||||
|
||||
**Product selection:**
|
||||
- Most recently added products (last 30 days)
|
||||
- Sorted by newest first
|
||||
- Exclude out-of-stock items
|
||||
- Show 10-20 products
|
||||
|
||||
**Layout:**
|
||||
Product slider, optional "New" badge on products. "Shop New Arrivals" link.
|
||||
|
||||
### Sale/Promotional Products
|
||||
|
||||
**Purpose**: Drive urgency and conversions, clear excess inventory.
|
||||
|
||||
**Product selection:**
|
||||
- Products with active sale prices from backend
|
||||
- Sorted by discount percentage
|
||||
- Limited time or seasonal sales
|
||||
|
||||
**Display:**
|
||||
Product slider with sale badges, strikethrough pricing, optional countdown timer (if time-limited sale).
|
||||
|
||||
## Value Propositions
|
||||
|
||||
### Trust & Convenience Features
|
||||
|
||||
**Purpose**: Build trust quickly, address common concerns (shipping cost, returns), differentiate from competitors.
|
||||
|
||||
**Common value propositions:**
|
||||
- Free shipping (over threshold or always)
|
||||
- Free returns (30/60/90 days)
|
||||
- Secure checkout
|
||||
- Customer support (24/7, phone, chat)
|
||||
- Fast shipping (2-day, same-day)
|
||||
- Quality guarantee or warranty
|
||||
|
||||
### Display Pattern
|
||||
|
||||
**Icon Row (most common):**
|
||||
3-4 icons with text below hero section. Icon + short text (truck icon + "Free Shipping"). Single row, centered. 100-150px per item.
|
||||
|
||||
**Placement:**
|
||||
Below hero section (most common) or above footer.
|
||||
|
||||
## Newsletter Signup
|
||||
|
||||
### Email Capture Section
|
||||
|
||||
**⚠️ IMPORTANT: Check footer first - don't duplicate newsletter forms.**
|
||||
|
||||
If your footer already includes a newsletter signup form, **do NOT add another newsletter section on the homepage**. Two newsletter forms on the same page:
|
||||
- Creates confusion (which one to use?)
|
||||
- Looks unprofessional and repetitive
|
||||
- Reduces conversion (decision fatigue)
|
||||
- Wastes valuable homepage space
|
||||
|
||||
**Decision:**
|
||||
- Footer has newsletter? → Skip homepage newsletter section, use that space for other content
|
||||
- Footer doesn't have newsletter? → Add homepage newsletter section (recommended placement: mid-page)
|
||||
- Want both? → Only if they serve different purposes (e.g., footer = general newsletter, homepage = specific campaign/offer)
|
||||
|
||||
**Purpose**: Grow email list for marketing, offer incentive to build relationship.
|
||||
|
||||
**Design essentials:**
|
||||
- Heading: "Stay in the Loop", "Get 10% Off"
|
||||
- Subheading: Benefit of subscribing (don't just say "subscribe")
|
||||
- Email input field
|
||||
- Submit button
|
||||
- Privacy note (optional): "We respect your privacy"
|
||||
|
||||
**Incentive (CRITICAL):**
|
||||
- 10% off first order (most common)
|
||||
- Early access to sales
|
||||
- Exclusive content or products
|
||||
- Free shipping code
|
||||
|
||||
**Layout options:**
|
||||
- Full-width section (dedicated section, background color, centered)
|
||||
- Inline form (between sections, smaller)
|
||||
- Footer newsletter (part of footer) - see footer.md
|
||||
|
||||
**Placement:**
|
||||
Mid-page (after 2-3 sections) or above footer.
|
||||
|
||||
## Content Hierarchy
|
||||
|
||||
### Section Order Recommendation
|
||||
|
||||
**Typical homepage structure:**
|
||||
1. Hero section
|
||||
2. Value propositions (free shipping, returns)
|
||||
3. Featured categories
|
||||
4. Bestsellers or Featured Products
|
||||
5. Promotional banner (mid-page, optional)
|
||||
6. New Arrivals
|
||||
7. Newsletter signup (skip if footer already has newsletter form)
|
||||
8. Footer
|
||||
|
||||
### Visual Rhythm
|
||||
|
||||
**Vary section types:**
|
||||
Product section → Banner → Product section. Avoid monotony (all product sections in a row). Mix text-heavy and image-heavy sections.
|
||||
|
||||
**Spacing:**
|
||||
Generous padding between sections (64-120px desktop, 40-60px mobile). Consistent spacing. Section backgrounds to create separation.
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Responsive layout:**
|
||||
Single column for most sections, stack elements vertically, larger touch targets (44px minimum), simplified navigation.
|
||||
|
||||
**Product sections:**
|
||||
Horizontal sliders with swipe gestures, or stacked product grids (2 columns). Smaller product cards optimized for mobile.
|
||||
|
||||
**Hero section:**
|
||||
Portrait aspect ratio (2:3 or 3:4), vertical text placement (center/bottom). See [hero.md](../components/hero.md) for mobile hero details.
|
||||
|
||||
**Performance:**
|
||||
Lazy load below-fold images, optimize hero image (<200KB), use WebP format. Mobile-first approach.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential elements:**
|
||||
|
||||
- [ ] Hero section with clear message and CTA
|
||||
- [ ] Featured categories (4-8 categories with images)
|
||||
- [ ] Categories fetched from backend dynamically
|
||||
- [ ] Bestsellers or Featured Products section
|
||||
- [ ] New Arrivals section
|
||||
- [ ] Value propositions (free shipping, returns, etc.)
|
||||
- [ ] Social proof (reviews, ratings, testimonials)
|
||||
- [ ] Newsletter signup form (only if footer doesn't have one - check footer first)
|
||||
- [ ] No duplicate newsletter forms (homepage + footer)
|
||||
- [ ] Footer with navigation and legal links
|
||||
- [ ] Mobile-responsive layout (single column, 44px touch targets)
|
||||
- [ ] Fast loading time (<3 seconds)
|
||||
- [ ] Optimized images (<200KB, WebP format)
|
||||
- [ ] Lazy loading for below-fold content
|
||||
- [ ] Backend integration (all content fetched from API)
|
||||
- [ ] Semantic HTML (main, section, h1, h2)
|
||||
- [ ] Proper heading hierarchy (h1 → h2 → h3)
|
||||
- [ ] Keyboard accessible
|
||||
- [ ] ARIA labels on sections
|
||||
- [ ] High contrast text (4.5:1 minimum)
|
||||
- [ ] Clear CTAs on every section
|
||||
@@ -0,0 +1,231 @@
|
||||
# Order Confirmation Page
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Essential Information](#essential-information)
|
||||
- [Order Details Display](#order-details-display)
|
||||
- [Next Steps Section](#next-steps-section)
|
||||
- [Layout Patterns](#layout-patterns)
|
||||
- [Call-to-Action Buttons](#call-to-action-buttons)
|
||||
- [Mobile Considerations](#mobile-considerations)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
The order confirmation page displays immediately after successful checkout. Purpose: Confirm purchase, provide order details, guide customers on next steps, build post-purchase confidence.
|
||||
|
||||
**Backend Integration:**
|
||||
|
||||
Fetch order details from backend API immediately after checkout completes. Do this based on backend integrated. Never hardcode or mock order data.
|
||||
|
||||
### Key Ecommerce Functions
|
||||
|
||||
- Confirm successful purchase (reduces anxiety)
|
||||
- Provide order reference number (for tracking and support)
|
||||
- Set delivery expectations (reduces "where's my order" inquiries)
|
||||
- Guide customer on next steps (reduces support load)
|
||||
- Encourage repeat purchases (continue shopping CTA)
|
||||
- Build post-purchase confidence (reduces buyer's remorse)
|
||||
|
||||
## Essential Information
|
||||
|
||||
### Success Message (CRITICAL)
|
||||
|
||||
**Confirmation headline:**
|
||||
Large, prominent heading, positive reassuring message, success icon (green checkmark), immediately visible above fold.
|
||||
|
||||
**Example messages:**
|
||||
- "Order Confirmed!"
|
||||
- "Thank you for your order!"
|
||||
- "Success! Your order is confirmed"
|
||||
|
||||
**Subheading:**
|
||||
Brief reassurance, email confirmation mention, delivery timeframe preview.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
✓ Order Confirmed!
|
||||
|
||||
Thank you for your purchase! We've sent a confirmation
|
||||
email to customer@example.com with your order details.
|
||||
```
|
||||
|
||||
### Order Number
|
||||
|
||||
**Display requirements:**
|
||||
- Very prominent
|
||||
- Clearly labeled "Order Number:" or "Order #"
|
||||
- Easy to select and copy (selectable text)
|
||||
- Monospace or sans-serif font
|
||||
- High contrast for visibility
|
||||
- Optional: Copy button next to number
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Order Number: #ORD-123456789
|
||||
```
|
||||
|
||||
### Email Confirmation Notice
|
||||
|
||||
Confirmation email was sent, email address used, check spam folder reminder (optional), resend email option (optional).
|
||||
|
||||
## Order Details Display
|
||||
|
||||
### Ordered Items List
|
||||
|
||||
Display per item:
|
||||
- Product image (thumbnail, 60-80px)
|
||||
- Product title (full name)
|
||||
- Variant information (size, color, etc.)
|
||||
- Quantity ("× 2")
|
||||
- Unit price
|
||||
- Line total (quantity × price)
|
||||
|
||||
### Order Summary (Pricing)
|
||||
|
||||
**Price breakdown:**
|
||||
- Subtotal (sum of items)
|
||||
- Shipping cost (with method name)
|
||||
- Tax (if applicable)
|
||||
- Discount/promo code (if used, show savings)
|
||||
- **Order Total** (bold, larger font)
|
||||
|
||||
**Medusa pricing note:**
|
||||
Medusa stores prices as-is (not in cents). Display prices directly without dividing by 100. Example: If backend returns 49.99, display $49.99.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Subtotal: $139.97
|
||||
Shipping (Express): $5.99
|
||||
Tax: $11.20
|
||||
Discount (SAVE10): -$14.00
|
||||
─────────────────────────────
|
||||
Order Total: $143.16
|
||||
```
|
||||
|
||||
### Shipping and Billing Information
|
||||
|
||||
**Shipping address:**
|
||||
Recipient name, complete address, phone number, shipping method selected, estimated delivery date.
|
||||
|
||||
**Billing address:**
|
||||
If same as shipping: "Same as shipping address". If different: Show full billing address.
|
||||
|
||||
**Payment information:**
|
||||
Payment method type, last 4 digits (if card), alternative methods (PayPal email, Apple Pay). **Never show full card number.**
|
||||
|
||||
## Next Steps Section
|
||||
|
||||
### What Happens Next (CRITICAL)
|
||||
|
||||
**Timeline guidance:**
|
||||
Order processing information, shipment timeline, when tracking becomes available, expected delivery date.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
What's Next?
|
||||
|
||||
1. Order Processing (1-2 business days)
|
||||
We're carefully preparing your items for shipment.
|
||||
|
||||
2. Shipment Notification
|
||||
You'll receive an email with tracking information
|
||||
when your order ships.
|
||||
|
||||
3. Delivery (By January 30)
|
||||
Your package will arrive at your address.
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
Sets clear expectations, reduces "where's my order" inquiries, builds confidence in process.
|
||||
|
||||
## Layout Patterns
|
||||
|
||||
### Single Column Layout (Recommended)
|
||||
|
||||
Full-width content, centered on page, all sections stacked vertically. Mobile-friendly by default.
|
||||
|
||||
**Section order:**
|
||||
1. Success message and order number
|
||||
2. Email confirmation notice
|
||||
3. Order items list
|
||||
4. Order summary (pricing)
|
||||
5. Shipping address
|
||||
6. Billing address
|
||||
7. Payment method
|
||||
8. Next steps/timeline
|
||||
9. CTAs (continue shopping, print, track)
|
||||
|
||||
### Two-Column Layout (Desktop Alternative)
|
||||
|
||||
- Left column (60-70%): Main content (success, order number, items, addresses, next steps)
|
||||
- Right column (30-40%): Sidebar (order summary, CTAs, tracking)
|
||||
- Mobile: Collapses to single column
|
||||
|
||||
## Call-to-Action Buttons
|
||||
|
||||
### Primary Actions
|
||||
|
||||
**Continue Shopping (MOST IMPORTANT):**
|
||||
Large, prominent button (primary color), returns to homepage or shop page. Text: "Continue Shopping" or "Back to Store". Encourages repeat visits.
|
||||
|
||||
### Secondary Actions
|
||||
|
||||
**Create Account (for guest orders):**
|
||||
Encourage account creation, pre-fill email from order, benefits messaging ("Track orders easily"). Optional, not required.
|
||||
|
||||
**Print Receipt:**
|
||||
Print-friendly CSS, button to print page.
|
||||
|
||||
**Contact Support:**
|
||||
Link to support page or contact form, phone number (if available), help with order questions.
|
||||
|
||||
**Button layout:**
|
||||
Primary action prominent (filled button), secondary actions less prominent (outline or link), adequate spacing (16-24px), mobile full-width.
|
||||
|
||||
## Mobile Considerations
|
||||
|
||||
**Single column only:**
|
||||
Full-width sections, generous padding (16-20px), larger text for important info, touch-friendly buttons.
|
||||
|
||||
**Order number:**
|
||||
Extra large (28-36px), highly visible, easy to read and reference, tap to copy (if implemented).
|
||||
|
||||
**Buttons:**
|
||||
Full-width or near full-width (min 90%), 48-56px height (touch-friendly), 16px spacing between buttons.
|
||||
|
||||
**Quick actions:**
|
||||
- Tap phone number to call support
|
||||
- Tap to copy order number
|
||||
- Add delivery date to calendar
|
||||
- Share order details
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential elements:**
|
||||
|
||||
- [ ] Large success message (32-48px heading)
|
||||
- [ ] Green checkmark or success icon
|
||||
- [ ] Prominent order number (24-32px, selectable)
|
||||
- [ ] Email confirmation notice
|
||||
- [ ] Order items list with images
|
||||
- [ ] Item details (title, variant, quantity, price)
|
||||
- [ ] Order summary (subtotal, shipping, tax, total)
|
||||
- [ ] Shipping address displayed
|
||||
- [ ] Billing address (or "same as shipping")
|
||||
- [ ] Payment method (last 4 digits only)
|
||||
- [ ] Estimated delivery date
|
||||
- [ ] Shipping method name
|
||||
- [ ] "What's Next" section (timeline)
|
||||
- [ ] Continue Shopping button (primary CTA)
|
||||
- [ ] Print receipt button
|
||||
- [ ] Contact support link
|
||||
- [ ] Guest orders: Create account CTA (optional)
|
||||
- [ ] Backend integration (fetch order from API)
|
||||
- [ ] Mobile-responsive (single column, full-width buttons)
|
||||
- [ ] Semantic HTML (main, section, h1, h2)
|
||||
- [ ] ARIA labels on sections
|
||||
- [ ] Live region announcing success
|
||||
- [ ] Keyboard navigation supported
|
||||
- [ ] High contrast text (4.5:1 minimum)
|
||||
@@ -0,0 +1,527 @@
|
||||
# Product Detail Page Layout
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Layout Structure](#layout-structure)
|
||||
- [Price Display and Medusa Integration](#price-display-and-medusa-integration)
|
||||
- [Variant Selection (Critical)](#variant-selection-critical)
|
||||
- [Stock Availability](#stock-availability)
|
||||
- [Add to Cart Behavior](#add-to-cart-behavior)
|
||||
- [Product Details Organization](#product-details-organization)
|
||||
- [Related Products Strategy](#related-products-strategy)
|
||||
- [Trust Signals and Conversion](#trust-signals-and-conversion)
|
||||
- [Mobile Optimization](#mobile-optimization)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Most critical page for conversion. Customers make purchase decisions here based on product information, images, reviews, and trust signals.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- High-quality product images with zoom capability
|
||||
- Clear price display (handle variant price changes)
|
||||
- Variant selection (size, color, material)
|
||||
- Stock availability indicators
|
||||
- Prominent "Add to Cart" with proper feedback
|
||||
- Product details (description, specifications)
|
||||
- Customer reviews and ratings
|
||||
- Related product recommendations
|
||||
- Trust signals (shipping, returns, secure checkout)
|
||||
- Mobile-optimized (60%+ traffic)
|
||||
|
||||
### Routing Pattern
|
||||
|
||||
**CRITICAL: Always use dynamic routes, NEVER static pages.**
|
||||
|
||||
Product detail pages must use dynamic routes that accept a parameter (handle, slug, or ID):
|
||||
|
||||
**Correct examples:**
|
||||
- Next.js App Router: `app/products/[handle]/page.tsx`
|
||||
- Next.js Pages Router: `pages/products/[handle].tsx`
|
||||
- SvelteKit: `routes/products/[handle]/+page.svelte`
|
||||
- TanStack Start: `routes/products/$handle.tsx`
|
||||
- Remix: `routes/products.$handle.tsx`
|
||||
|
||||
**Wrong examples:**
|
||||
- ❌ `pages/products/blue-shirt.tsx` (static file per product)
|
||||
- ❌ `pages/products/red-shoes.tsx` (doesn't scale)
|
||||
|
||||
Fetch product data in the dynamic route based on the handle/ID parameter from the URL.
|
||||
|
||||
## Layout Structure
|
||||
|
||||
**Desktop (two-column):**
|
||||
- Left: Product images (50-60% width)
|
||||
- Right: Product info, variants, add to cart (40-50%)
|
||||
- Below: Product details, reviews, related products (full-width)
|
||||
|
||||
**Mobile (stacked):**
|
||||
- Images at top (full-width, swipeable)
|
||||
- Product info below (title, price, rating)
|
||||
- Variants and add to cart
|
||||
- Accordion for product details
|
||||
- Reviews section
|
||||
- Related products
|
||||
- Sticky "Add to Cart" bar at bottom
|
||||
|
||||
**Sticky sidebar option (desktop):**
|
||||
- Product info column stays visible during scroll
|
||||
- Add to cart always accessible
|
||||
- Useful for long product descriptions
|
||||
- Improves conversion
|
||||
|
||||
## Price Display
|
||||
|
||||
### Standard Price Display
|
||||
|
||||
**Current price:**
|
||||
- Large, bold font (28-36px)
|
||||
- Currency symbol included ($49.99)
|
||||
- Primary color or black
|
||||
|
||||
**Sale pricing:**
|
||||
- Original price with strikethrough: ~~$79.99~~ $49.99
|
||||
- Sale price in red or brand color
|
||||
- "Save X%" badge nearby
|
||||
- Example: Save 37%
|
||||
|
||||
**Variant price changes:**
|
||||
- **When no variant selected**: Show "From $X" where X is the minimum variant price across all variants
|
||||
- **When variant selected**: Update price dynamically to show the exact variant price
|
||||
- No page reload required
|
||||
- Show price change clearly (highlight briefly on change)
|
||||
- Example: Product with variants priced at $29.99, $34.99, $39.99 → Show "From $29.99" initially
|
||||
|
||||
### Medusa Pricing (CRITICAL)
|
||||
|
||||
**Important difference from Stripe:**
|
||||
- Medusa stores prices as-is (e.g., 49.99)
|
||||
- Display directly: If API returns 49.99, show $49.99
|
||||
- **DON'T divide by 100** (unlike Stripe which stores in cents)
|
||||
- Example: Medusa 49.99 → Display $49.99 (NOT $0.4999)
|
||||
|
||||
**Multi-currency (Medusa):**
|
||||
- Medusa supports multi-region pricing
|
||||
- Display price in user's region currency
|
||||
- Fetch pricing from selected region
|
||||
- Show currency code (usd, eur, etc.)
|
||||
|
||||
## Variant Selection (Critical)
|
||||
|
||||
This is a complex ecommerce-specific challenge. Variants affect price, stock, and images.
|
||||
|
||||
### Variant Complexity
|
||||
|
||||
**Key challenges:**
|
||||
- Multiple variant types (size, color, material)
|
||||
- Variant availability varies (some sizes out of stock)
|
||||
- Prices may differ by variant
|
||||
- Images change by color variant
|
||||
- Stock levels per variant
|
||||
- Combinations may not exist (size M + color Red might not exist)
|
||||
|
||||
**Fetch from backend:**
|
||||
```typescript
|
||||
// Get all variants for product
|
||||
// Change this based on the backend integrated
|
||||
const product = await fetch(`/products/${id}?fields=*variants`)
|
||||
// Returns variants with: id, sku, options, calculated_price, inventory_quantity
|
||||
```
|
||||
|
||||
### Variant Selection Patterns
|
||||
|
||||
**Use Button Group when:**
|
||||
- 2-8 options per variant type
|
||||
- Size selection (XS, S, M, L, XL)
|
||||
- Simple color options (5-6 colors)
|
||||
- Users need to see all options at once
|
||||
|
||||
**Benefits:**
|
||||
- Visible options (no click to reveal)
|
||||
- Faster selection
|
||||
- Clear visual feedback
|
||||
- Better UX
|
||||
|
||||
**Use Dropdown when:**
|
||||
- 10+ options per variant type
|
||||
- Material/style options with long names
|
||||
- Space-constrained layouts
|
||||
- Mobile optimization needed
|
||||
|
||||
**Benefits:**
|
||||
- Saves space
|
||||
- Works better for many options
|
||||
- Mobile-friendly
|
||||
|
||||
**Use Visual Swatches when:**
|
||||
- Color or pattern variations
|
||||
- Material with visual differences
|
||||
- Visual is key to decision
|
||||
- Fashion, home decor, customizable products
|
||||
|
||||
**Implementation:**
|
||||
- Circular/square swatches (40-48px)
|
||||
- Border on selected
|
||||
- Show product image in that color when selected
|
||||
- Color name on hover
|
||||
- Gray out unavailable colors
|
||||
|
||||
### Variant Selection Flow
|
||||
|
||||
**Critical sequence:**
|
||||
1. User selects first variant type (e.g., Color: Blue)
|
||||
2. **Update available options** for other variant types
|
||||
3. Show only size options available for Blue color
|
||||
4. Gray out/disable unavailable combinations
|
||||
5. Update price if variant price differs
|
||||
6. Update main product image to show selected variant
|
||||
7. Update stock availability
|
||||
8. Enable/disable "Add to Cart" based on availability
|
||||
|
||||
**Example: Two variants (Color + Size)**
|
||||
```typescript
|
||||
// When color selected
|
||||
// Change this based on the backend integrated
|
||||
onColorSelect(color) {
|
||||
// Find selected variant
|
||||
const selectededVariant = product.variants.find((variant) => variant.options?.every(
|
||||
(optionValue) => optionValue.id === selectedOptions[optionValue.option_id!]
|
||||
))
|
||||
|
||||
// Check if size is selected and update price
|
||||
if (selectededVariant) {
|
||||
const variant = findVariant(color, selectedSize)
|
||||
updatePrice(variant.price)
|
||||
updateStock(variant.inventory_quantity)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Validation and Error Handling
|
||||
|
||||
**Prevent adding without selection:**
|
||||
- Disable "Add to Cart" until all required variants selected
|
||||
- Or: Show error message "Please select a size"
|
||||
- Highlight missing selection (red border around options)
|
||||
- Scroll to variant selection on error
|
||||
|
||||
**Handle out of stock variants:**
|
||||
- Gray out unavailable options
|
||||
- "Out of stock" text on hover
|
||||
- Don't allow selection of out of stock variants
|
||||
- Suggest alternative variants if available
|
||||
|
||||
**Handle variant not found:**
|
||||
- When combination doesn't exist (Size M + Color Red)
|
||||
- Disable second option when first selected
|
||||
- Show only valid combinations
|
||||
- Or: Show "This combination is not available"
|
||||
|
||||
## Stock Availability
|
||||
|
||||
**Display patterns:**
|
||||
|
||||
**In stock:**
|
||||
- Green indicator (✓ or dot)
|
||||
- "In stock" or "Available"
|
||||
- Quantity if low: "Only 3 left"
|
||||
- Encourages urgency without being pushy
|
||||
|
||||
**Out of stock:**
|
||||
- Red indicator (✗ or dot)
|
||||
- "Out of stock" message
|
||||
- Disable "Add to Cart" button (grayed out)
|
||||
- Offer "Notify me when available"
|
||||
- Email capture for restock notifications (if supported by backend)
|
||||
|
||||
**Low stock warning:**
|
||||
- "Only X left in stock"
|
||||
- Shows scarcity (increases urgency)
|
||||
- Typically show when <= 5 items
|
||||
- Orange/yellow color
|
||||
|
||||
**Pre-order:**
|
||||
- "Pre-order now" status
|
||||
- Expected availability date: "Ships on [Date]"
|
||||
- Different button text: "Pre-order" instead of "Add to Cart"
|
||||
- Charge now or later (specify)
|
||||
|
||||
**Backend integration:**
|
||||
```typescript
|
||||
// Fetch stock for selected variant
|
||||
const stock = selectedVariant.inventory_quantity
|
||||
|
||||
if (stock === 0) {
|
||||
showOutOfStock()
|
||||
} else if (stock <= 5) {
|
||||
showLowStock(stock) // "Only 3 left"
|
||||
} else {
|
||||
showInStock()
|
||||
}
|
||||
```
|
||||
|
||||
## Add to Cart Behavior
|
||||
|
||||
**Button states:**
|
||||
- Default: Enabled (after variant selected)
|
||||
- Hover: Slight color change or scale
|
||||
- Loading: Spinner inside button (during API call)
|
||||
- Success: Checkmark briefly, then revert
|
||||
- Disabled: Grayed out (no variant or out of stock)
|
||||
|
||||
**Click behavior (Critical):**
|
||||
1. Show loading state (disable button, show spinner)
|
||||
2. Call API to add item to cart (backend)
|
||||
3. **Optimistic UI**: Update cart count immediately (before API response)
|
||||
4. Show success feedback (toast, checkmark, or cart popup)
|
||||
5. Update cart count in navbar header
|
||||
6. **DON'T navigate away** - stay on product page
|
||||
7. Handle errors: restore count if API fails
|
||||
|
||||
**Success feedback options:**
|
||||
- Toast notification: "Added to cart" (top-right)
|
||||
- Cart popup: Show mini cart with items (see cart-popup.md)
|
||||
- Checkmark in button briefly, then revert
|
||||
- All three combined (checkmark + toast or cart popup)
|
||||
|
||||
**Error handling:**
|
||||
```typescript
|
||||
async function addToCart(variantId, quantity) {
|
||||
try {
|
||||
// Optimistic update
|
||||
updateCartCountUI(+quantity)
|
||||
|
||||
// API call
|
||||
// Change this based on the backend integrated
|
||||
await fetch(`/store/carts/${cartId}/line-items`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ variant_id: variantId, quantity })
|
||||
})
|
||||
|
||||
// Success feedback
|
||||
showToast('Added to cart')
|
||||
showCartPopup() // Optional
|
||||
} catch (error) {
|
||||
// Revert optimistic update
|
||||
updateCartCountUI(-quantity)
|
||||
|
||||
// Show error
|
||||
if (error.message === 'OUT_OF_STOCK') {
|
||||
showError('Sorry, this item is now out of stock')
|
||||
updateStockStatus('out_of_stock')
|
||||
} else {
|
||||
showError('Failed to add to cart. Please try again.')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Buy Now button (optional):**
|
||||
- Skip cart, go directly to checkout
|
||||
- Useful for: high-value items, single-item stores, decisive customers
|
||||
- Secondary button below "Add to Cart"
|
||||
- Text: "Buy Now" or "Buy It Now"
|
||||
- Add to cart + redirect to checkout in one action
|
||||
|
||||
## Product Details Organization
|
||||
|
||||
### Decision: Tabs vs Accordion
|
||||
|
||||
**Use Tabs (desktop) when:**
|
||||
- 3-5 distinct sections
|
||||
- Each section has substantial content
|
||||
- Users may want to compare sections
|
||||
- Desktop has screen space
|
||||
- Examples: Description, Specifications, Shipping, Reviews
|
||||
|
||||
**Use Accordion (mobile) always:**
|
||||
- Saves vertical space
|
||||
- Users expand what they need
|
||||
- Standard mobile pattern
|
||||
- Collapses after reading
|
||||
|
||||
**Hybrid approach (recommended):**
|
||||
- Tabs on desktop (horizontal navigation)
|
||||
- Accordion on mobile (vertical expansion)
|
||||
- Same content, different presentation
|
||||
- Best of both worlds
|
||||
|
||||
### Common Sections
|
||||
|
||||
**Description:**
|
||||
- Product overview (2-4 paragraphs)
|
||||
- Key features (bullet points)
|
||||
- Use cases
|
||||
- Materials and craftsmanship
|
||||
|
||||
**Specifications:**
|
||||
- Technical details (table format)
|
||||
- Dimensions, weight, materials
|
||||
- Care instructions
|
||||
- Compatibility information
|
||||
|
||||
**Shipping & Returns:**
|
||||
- Shipping options and costs
|
||||
- Delivery timeframes
|
||||
- Return policy (30 days, 60 days)
|
||||
- Return process
|
||||
- Link to full policy page
|
||||
|
||||
**Reviews:**
|
||||
- Embedded in tab/accordion
|
||||
- Or: Separate section below
|
||||
- Filter by rating, sort by date
|
||||
- Review submission form
|
||||
|
||||
## Related Products Strategy
|
||||
|
||||
**Types of recommendations:**
|
||||
|
||||
**"You May Also Like" (Similar products):**
|
||||
- Same category, similar price point
|
||||
- Algorithm: category match + price range
|
||||
- Goal: Show alternatives if unsure about current product
|
||||
|
||||
**"Frequently Bought Together" (Complementary):**
|
||||
- Products commonly purchased together
|
||||
- Algorithm: order history analysis
|
||||
- Goal: Increase average order value
|
||||
- Example: Phone + Case + Screen Protector
|
||||
- Show bundle discount if available
|
||||
|
||||
**"Recently Viewed" (Browsing history):**
|
||||
- User's browsing history (session or logged-in)
|
||||
- Helps users return to products they liked
|
||||
- Goal: Reduce decision paralysis
|
||||
|
||||
**"Customers Also Viewed":**
|
||||
- Products viewed by others who viewed this
|
||||
- Algorithm: co-viewing patterns
|
||||
- Goal: Discovery and alternatives
|
||||
|
||||
### Display Pattern
|
||||
|
||||
**Product slider:**
|
||||
- 4-6 products visible (desktop)
|
||||
- 2-3 visible (mobile)
|
||||
- Horizontal scrolling (swipe on mobile)
|
||||
- Product cards: image, title, price, rating
|
||||
- Optional: Quick "Add to Cart" on hover
|
||||
|
||||
**Placement:**
|
||||
- Below product details and reviews
|
||||
- Above footer
|
||||
- Full-width section
|
||||
- Clear heading for each type
|
||||
|
||||
**Backend integration:**
|
||||
```typescript
|
||||
// Fetch recommendations
|
||||
// Change this based on the backend integrated
|
||||
const recommendations = await fetch(`/products/${id}/recommendations`)
|
||||
// Returns: similar, bought_together, recently_viewed
|
||||
```
|
||||
|
||||
## Trust Signals and Conversion
|
||||
|
||||
**Essential trust signals:**
|
||||
|
||||
**Near Add to Cart:**
|
||||
- Free shipping badge (if applicable)
|
||||
- Free returns icon + text
|
||||
- Secure checkout icon
|
||||
- Money-back guarantee
|
||||
- Warranty information (if applicable)
|
||||
|
||||
**Below product title:**
|
||||
- Customer rating and review count (4.8 ★ 324 reviews)
|
||||
- Link to reviews section
|
||||
- "Best seller" or "Top rated" badge
|
||||
|
||||
**Payment methods:**
|
||||
- Accepted payment icons (Visa, Mastercard, PayPal, Apple Pay)
|
||||
- Small icons (40px)
|
||||
- Below "Add to Cart" or in footer
|
||||
- Shows payment options available
|
||||
|
||||
**For new/unknown brands:**
|
||||
- Customer testimonials
|
||||
- "Join 10,000+ happy customers"
|
||||
- Security badges (if legitimate - don't fake)
|
||||
- Social proof (Instagram photos, user content)
|
||||
- Clear contact information
|
||||
|
||||
**For high-value products:**
|
||||
- Detailed specifications
|
||||
- Professional photography
|
||||
- Video demonstrations
|
||||
- Warranty details prominently displayed
|
||||
- Customer service contact visible
|
||||
|
||||
## Mobile Optimization
|
||||
|
||||
**Critical mobile patterns:**
|
||||
|
||||
**Sticky "Add to Cart" bar:**
|
||||
- Fixed at bottom of screen
|
||||
- Always accessible (no scrolling needed)
|
||||
- Shows: Price + "Add to Cart" button
|
||||
- Appears after scrolling past fold
|
||||
- Higher conversion rates
|
||||
|
||||
**Image gallery:**
|
||||
- Full-width swipeable carousel
|
||||
- Pinch to zoom
|
||||
- Dot indicators (1/5, 2/5)
|
||||
- Tap to open full-screen view
|
||||
|
||||
**Variant selection:**
|
||||
- Large touch targets (44-48px)
|
||||
- Visual swatches easier than dropdowns
|
||||
- Clear selected state
|
||||
- Error messages visible
|
||||
|
||||
**Accordion for details:**
|
||||
- Description, Specs, Shipping as accordion
|
||||
- Starts collapsed (save space)
|
||||
- User expands what they need
|
||||
- Clear expand/collapse indicators
|
||||
|
||||
**Reviews section:**
|
||||
- Expandable (start with 2-3 reviews)
|
||||
- "Show more" button
|
||||
- Filter by rating
|
||||
- Star rating distribution chart
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential product detail page features:**
|
||||
|
||||
- [ ] High-quality product images with zoom
|
||||
- [ ] Price displayed correctly (Medusa: use value as-is, not divided)
|
||||
- [ ] Price shows "From $X" when no variant selected (X = minimum variant price)
|
||||
- [ ] Variant selection required before adding to cart
|
||||
- [ ] Variant selection updates: price, stock, image
|
||||
- [ ] Disable unavailable variant options (gray out)
|
||||
- [ ] Stock availability indicator (in stock, low stock, out of stock)
|
||||
- [ ] "Only X left" shown when stock is low (<=5)
|
||||
- [ ] Add to Cart disabled until variant selected
|
||||
- [ ] Optimistic UI update (cart count updates immediately)
|
||||
- [ ] Success feedback (toast, cart popup, or checkmark)
|
||||
- [ ] Stay on product page after adding (don't navigate away)
|
||||
- [ ] Error handling (out of stock, API failure)
|
||||
- [ ] Product description and specifications
|
||||
- [ ] Customer reviews and ratings
|
||||
- [ ] Related products recommendations (similar, bought together)
|
||||
- [ ] Trust signals (free shipping, returns, secure checkout)
|
||||
- [ ] Payment method icons displayed
|
||||
- [ ] Breadcrumb navigation
|
||||
- [ ] Mobile: Swipeable image gallery
|
||||
- [ ] Mobile: Accordion for product details
|
||||
- [ ] Mobile: Sticky Add to Cart bar (optional but effective)
|
||||
- [ ] Tabs on desktop, accordion on mobile (hybrid)
|
||||
- [ ] Fast loading (<2s, optimize images)
|
||||
- [ ] Keyboard accessible (tab through options, enter to add)
|
||||
- [ ] ARIA labels on variant selection (role="group", aria-label)
|
||||
@@ -0,0 +1,520 @@
|
||||
# Product Listing Page Layout
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Reusable Component Architecture](#reusable-component-architecture-recommended)
|
||||
- [Decision: Pagination vs Infinite Scroll vs Load More](#decision-pagination-vs-infinite-scroll-vs-load-more)
|
||||
- [Decision: Filter Pattern Selection](#decision-filter-pattern-selection)
|
||||
- [Product Grid Layout](#product-grid-layout)
|
||||
- [Filtering Strategy](#filtering-strategy)
|
||||
- [Sorting Strategy](#sorting-strategy)
|
||||
- [Backend Integration](#backend-integration)
|
||||
- [Empty and No Results States](#empty-and-no-results-states)
|
||||
- [Performance Optimization](#performance-optimization)
|
||||
- [Mobile Optimization](#mobile-optimization)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Primary browsing interface where users compare products, apply filters, and navigate to product details. Critical for product discovery and conversion.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Responsive product grid (3-4 columns desktop, 2 mobile)
|
||||
- Filtering (categories, price, attributes)
|
||||
- Sorting options (price, popularity, newest)
|
||||
- Pagination, infinite scroll, or load more
|
||||
- Results count and active filter indicators
|
||||
- Clear "no results" state with suggestions
|
||||
- Fast loading and filtering (<1s filter updates)
|
||||
- Backend integration for dynamic filtering
|
||||
|
||||
### Reusable Component Architecture (RECOMMENDED)
|
||||
|
||||
**Build product listing as a reusable component that works across multiple pages:**
|
||||
|
||||
✅ **Use the same product listing component for:**
|
||||
- "Shop All" page (all products, no category filter)
|
||||
- Category pages (filtered by specific category)
|
||||
- Search results page (filtered by search query)
|
||||
- Sale/Promotion pages (filtered by discount/promotion)
|
||||
- Collection pages (curated product sets)
|
||||
- Brand pages (filtered by brand)
|
||||
|
||||
**Benefits of reusable approach:**
|
||||
- Single source of truth for product browsing UI
|
||||
- Consistent filtering, sorting, and pagination behavior across entire site
|
||||
- Easier maintenance (fix bugs once, applies everywhere)
|
||||
- Better user experience (familiar interface on every product browsing page)
|
||||
- Significantly less code duplication
|
||||
|
||||
**What to make configurable:**
|
||||
- Initial filter parameters (category ID, search query, promotion ID, brand, etc.)
|
||||
- Page title and breadcrumbs
|
||||
- Whether to show filters sidebar (some pages may hide certain filters)
|
||||
- Default sort order (category: featured, search: relevance, sale: discount %)
|
||||
- Number of products per page
|
||||
- Filter options available (hide category filter on category pages, etc.)
|
||||
|
||||
**Common mistake:**
|
||||
- ❌ Creating separate components/pages for "Shop All", category pages, and search results with duplicated filtering/sorting/pagination logic
|
||||
- ✅ Build one reusable ProductListing component that accepts filter parameters and reuse it across all product browsing pages
|
||||
|
||||
### Routing Pattern
|
||||
|
||||
**CRITICAL: Always use dynamic routes for category pages, NEVER static pages.**
|
||||
|
||||
Category/listing pages must use dynamic routes that accept a parameter (handle, slug, or category ID):
|
||||
|
||||
**Correct examples:**
|
||||
- Next.js App Router: `app/categories/[handle]/page.tsx`
|
||||
- Next.js Pages Router: `pages/categories/[handle].tsx`
|
||||
- SvelteKit: `routes/categories/[handle]/+page.svelte`
|
||||
- TanStack Start: `routes/categories/$handle.tsx`
|
||||
- Remix: `routes/categories.$handle.tsx`
|
||||
|
||||
**Wrong examples:**
|
||||
- ❌ `pages/categories/women.tsx` (static file per category)
|
||||
- ❌ `pages/categories/men.tsx` (doesn't scale)
|
||||
|
||||
Fetch category products in the dynamic route based on the handle/ID parameter from the URL.
|
||||
|
||||
## Decision: Pagination vs Infinite Scroll vs Load More
|
||||
|
||||
This is a critical ecommerce decision that affects user experience, SEO, and technical implementation.
|
||||
|
||||
### Use Pagination When:
|
||||
|
||||
**User needs:**
|
||||
- Return to specific result pages
|
||||
- Precise control over browsing
|
||||
- Professional/research shopping (compare systematically)
|
||||
- B2B shoppers (procurement, large orders)
|
||||
|
||||
**Product characteristics:**
|
||||
- Position matters (rankings, bestsellers)
|
||||
- Large catalog with stable ordering
|
||||
- Products require careful comparison
|
||||
|
||||
**Technical benefits:**
|
||||
- SEO-friendly (unique URL per page)
|
||||
- Better for indexing and crawling
|
||||
- Easier back button support
|
||||
- Lower memory usage
|
||||
|
||||
**Implementation:**
|
||||
```typescript
|
||||
// URL structure: /products?page=2&category=shirts
|
||||
// Each page has unique URL for SEO
|
||||
```
|
||||
|
||||
**Best for:**
|
||||
- Desktop-heavy audience
|
||||
- B2B ecommerce
|
||||
- Product comparison shopping
|
||||
- Catalog with 100+ products
|
||||
|
||||
### Use Infinite Scroll When:
|
||||
|
||||
**User needs:**
|
||||
- Exploratory browsing behavior
|
||||
- Mobile-first experience
|
||||
- Seamless discovery flow
|
||||
- Fashion/visual shopping
|
||||
|
||||
**Product characteristics:**
|
||||
- Visual-heavy products (fashion, art, photography)
|
||||
- Impulse purchases
|
||||
- Discovery-focused (Pinterest-style)
|
||||
|
||||
**Technical considerations:**
|
||||
- More complex to implement
|
||||
- Requires careful SEO handling (pagination URLs still needed)
|
||||
- Higher memory usage (all loaded products stay in DOM)
|
||||
- Need to handle browser back button carefully
|
||||
|
||||
**Implementation:**
|
||||
```typescript
|
||||
// Load more when user scrolls to bottom
|
||||
// Keep pagination in URL for SEO: /products?page=2
|
||||
// Use Intersection Observer API for detection
|
||||
```
|
||||
|
||||
**Best for:**
|
||||
- Mobile-first stores (>60% mobile traffic)
|
||||
- Fashion, home decor, visual products
|
||||
- Younger demographic (18-34)
|
||||
- Discovery-focused shopping
|
||||
|
||||
### Use "Load More" Button When:
|
||||
|
||||
**Benefits of compromise:**
|
||||
- User controls when to load (not automatic)
|
||||
- Footer remains accessible (important for policies, contact)
|
||||
- Better for slower connections (international users)
|
||||
- Accessibility friendly (no automatic loading)
|
||||
- Lower memory usage than infinite scroll
|
||||
|
||||
**Implementation:**
|
||||
```typescript
|
||||
// Button triggers next page load
|
||||
// Append products to existing grid
|
||||
// Show count: "Load 24 More Products"
|
||||
```
|
||||
|
||||
**Best for:**
|
||||
- International audience (varying connection speeds)
|
||||
- Footer content is important (legal, policies, contact)
|
||||
- Accessibility concerns with infinite scroll
|
||||
- Compromise between pagination and infinite scroll
|
||||
|
||||
### Hybrid Approach (Recommended):
|
||||
|
||||
Combine patterns based on context:
|
||||
- Pagination for SEO (canonical URLs)
|
||||
- Infinite scroll for UX (on user interaction)
|
||||
- Load more for control (user-triggered)
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// Desktop: Pagination at bottom + infinite scroll option
|
||||
// Mobile: Infinite scroll with pagination URLs for SEO
|
||||
// All: Preserve scroll position on back button
|
||||
```
|
||||
|
||||
## Decision: Filter Pattern Selection
|
||||
|
||||
### Sidebar Filters (Desktop)
|
||||
|
||||
**Use when:**
|
||||
- Many filter options (5+ categories)
|
||||
- Complex product attributes
|
||||
- Power users (B2B, professional shoppers)
|
||||
- Desktop-heavy traffic
|
||||
|
||||
**Layout:**
|
||||
- Left sidebar (250-320px wide)
|
||||
- Sticky position (scrolls with page)
|
||||
- Collapsible sections (accordion)
|
||||
- Apply immediately (no "Apply" button)
|
||||
|
||||
### Top Filters (Desktop)
|
||||
|
||||
**Use when:**
|
||||
- Few filter options (2-4 key filters)
|
||||
- Maximize grid space (full-width layout)
|
||||
- Simple product categories
|
||||
- Visual-first products (fashion)
|
||||
|
||||
**Layout:**
|
||||
- Horizontal filter bar above grid
|
||||
- Dropdowns or button toggles
|
||||
- Limited options (price, category, brand)
|
||||
- Compact design
|
||||
|
||||
### Drawer Filters (Mobile - Always)
|
||||
|
||||
**Pattern:**
|
||||
- "Filters" button at top (shows active count badge)
|
||||
- Slide-out drawer (full-screen or 80% width)
|
||||
- Accordion sections
|
||||
- "Apply" button at bottom (batch filtering)
|
||||
- "Clear All" option
|
||||
|
||||
**Why batch filtering on mobile:**
|
||||
- Prevents multiple re-renders on slow connections
|
||||
- User can adjust multiple filters before applying
|
||||
- Better mobile UX (less disruptive)
|
||||
|
||||
## Product Grid Layout
|
||||
|
||||
**Responsive columns:**
|
||||
- Large desktop (>1440px): 4 columns
|
||||
- Desktop (1024-1440px): 3-4 columns
|
||||
- Tablet (768-1024px): 3 columns
|
||||
- Mobile (< 768px): 2 columns
|
||||
|
||||
**Adjust based on product type:**
|
||||
- Fashion/lifestyle: 3-4 columns (more visible at once)
|
||||
- Electronics/detailed: 2-3 columns (larger cards, more detail)
|
||||
- Furniture/large items: 2-3 columns (showcase details)
|
||||
|
||||
**Product card essentials:**
|
||||
- Product image (primary)
|
||||
- Title (truncated to 2 lines)
|
||||
- Price (Medusa: display as-is, don't divide by 100)
|
||||
- Optional: Rating, badges, wishlist
|
||||
- See product-card.md for detailed guidelines
|
||||
|
||||
**Grid spacing:**
|
||||
- 16-24px gap (desktop)
|
||||
- 12-16px gap (mobile)
|
||||
- Equal height rows (optional, improves visual consistency)
|
||||
|
||||
## Filtering Strategy
|
||||
|
||||
### Filter Types by Purpose
|
||||
|
||||
**Category filters:**
|
||||
- Multi-select checkboxes
|
||||
- Hierarchical (parent-child categories)
|
||||
- Show product count per category
|
||||
- Example: "Shirts (24)" "T-Shirts (12)"
|
||||
|
||||
**Price range filter:**
|
||||
- Range slider (drag min/max)
|
||||
- Or: Predefined ranges ("$0-$50", "$50-$100")
|
||||
- Update dynamically as products filtered
|
||||
- Show min/max from current results
|
||||
|
||||
**Attribute filters (Size, Color, Brand):**
|
||||
- Multi-select checkboxes
|
||||
- Visual swatches for colors
|
||||
- Show available options based on current filters
|
||||
- Gray out unavailable combinations
|
||||
|
||||
**Availability filters:**
|
||||
- "In Stock" checkbox
|
||||
- "On Sale" checkbox
|
||||
- "New Arrivals" checkbox
|
||||
- Single purpose, clear value
|
||||
|
||||
### Filter Behavior
|
||||
|
||||
**Filter persistence:**
|
||||
- Save in URL parameters (shareable, bookmarkable)
|
||||
- Example: `/products?category=shirts&price=0-50&color=blue`
|
||||
- Restore filters on page reload
|
||||
- Clear all filters should reset URL
|
||||
|
||||
### Active Filters Display
|
||||
|
||||
**Show active filters:**
|
||||
- Above product grid
|
||||
- Pill/tag format: "Blue ✕" "Under $50 ✕"
|
||||
- Click X to remove individual filter
|
||||
- "Clear All" link to remove all filters
|
||||
- Count: "3 filters active"
|
||||
|
||||
## Sorting Strategy
|
||||
|
||||
### Common Sort Options
|
||||
|
||||
**Essential options:**
|
||||
- **Featured** (default): Store's recommended order (bestsellers, promoted)
|
||||
- **Price: Low to High**: Budget-conscious shoppers
|
||||
- **Price: High to Low**: Premium product seekers
|
||||
- **Newest**: Fashion, tech, time-sensitive products
|
||||
- **Best Selling**: Social proof, popular choices
|
||||
- **Top Rated**: Quality-focused shoppers
|
||||
|
||||
**Advanced options:**
|
||||
- Name: A-Z (alphabetical)
|
||||
- Discount: Highest % off (sale hunters)
|
||||
- Reviews: Most reviewed (validation seekers)
|
||||
|
||||
### Sort Implementation
|
||||
|
||||
**Display:**
|
||||
- Dropdown above product grid (right-aligned)
|
||||
- Label: "Sort by:" or just dropdown
|
||||
- Update products immediately on selection
|
||||
- Show current sort in URL: `/products?order=-created_at`
|
||||
|
||||
**Backend integration:**
|
||||
- Pass sort parameter to API (check backend docs for parameter name)
|
||||
- Common parameters: `order`, `sort`, `sort_by`
|
||||
- Common values: `-created_at` (desc), `+price` (asc), `-price` (desc)
|
||||
|
||||
**Preserve filters:**
|
||||
- Sorting doesn't clear filters
|
||||
- Maintains all active filters
|
||||
- Updates URL with sort parameter
|
||||
|
||||
## Backend Integration
|
||||
|
||||
### Fetching Products
|
||||
|
||||
**Query parameters to include:**
|
||||
- Category/collection filter (if applicable)
|
||||
- Pagination (limit, offset or cursor)
|
||||
- Sort order
|
||||
- Filter values (price, attributes, etc.)
|
||||
- For Medusa: `region_id` (required for correct pricing)
|
||||
|
||||
Check backend API documentation for exact parameter names and formats.
|
||||
|
||||
### Available Filters
|
||||
|
||||
**Dynamic filter updates:**
|
||||
- Show only relevant filters for current category
|
||||
- Display product count per filter option
|
||||
- Gray out options with 0 products
|
||||
- Update available options when filters change
|
||||
|
||||
### URL State Management
|
||||
|
||||
**Filter URL structure pattern:**
|
||||
`/products?category_id=123&order=-created_at&page=2&price=0-50`
|
||||
|
||||
**Benefits:**
|
||||
- Shareable links
|
||||
- Bookmarkable searches
|
||||
- Browser back/forward works correctly
|
||||
- SEO-friendly (crawlable filter combinations)
|
||||
|
||||
**Implementation approach:**
|
||||
- Read filters from URL query parameters on page load
|
||||
- Update URL when filters change using URLSearchParams and history.pushState
|
||||
- Parse URL parameters to reconstruct filter state
|
||||
|
||||
## Empty and No Results States
|
||||
|
||||
### No Products in Category
|
||||
|
||||
**When category is empty:**
|
||||
- Message: "No products available yet"
|
||||
- Subtext: "Check back soon for new arrivals"
|
||||
- CTA: "Browse all products" or "Go to home"
|
||||
- Alternative: Show related categories
|
||||
- Optional: Newsletter signup for notifications
|
||||
|
||||
### No Results from Filters
|
||||
|
||||
**When filters too restrictive:**
|
||||
- Message: "No products match your filters"
|
||||
- Subtext: "Try removing some filters or adjusting your criteria"
|
||||
- **Prominent "Clear All Filters" button**
|
||||
- Show which filters might be too restrictive
|
||||
- Suggestions: "Try expanding price range" or "Remove brand filter"
|
||||
|
||||
**Example:**
|
||||
```
|
||||
No products found
|
||||
|
||||
You filtered by:
|
||||
- Color: Blue
|
||||
- Size: XXL
|
||||
- Price: $0-$20
|
||||
|
||||
Try:
|
||||
• Removing size filter (only 2 XXL products)
|
||||
• Expanding price range
|
||||
• [Clear All Filters]
|
||||
```
|
||||
|
||||
### No Results from Search
|
||||
|
||||
**When search query returns nothing:**
|
||||
- Message: "No results for '[query]'"
|
||||
- Suggestions: Check spelling, try different keywords
|
||||
- CTA: Browse popular categories
|
||||
- Show search suggestions (similar queries)
|
||||
- Display popular or trending products
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Lazy Loading Images
|
||||
|
||||
**Implementation:**
|
||||
- Load images as they come into viewport
|
||||
- Use Intersection Observer API
|
||||
- Show placeholder or blur-up effect
|
||||
- Improves initial page load significantly
|
||||
|
||||
**Critical for ecommerce:**
|
||||
- Product listings have 24-100+ images per page
|
||||
- Lazy loading reduces initial load by 60-80%
|
||||
- Faster perceived performance
|
||||
|
||||
### Virtual Scrolling (Advanced)
|
||||
|
||||
**When to use:**
|
||||
- Very large catalogs (500+ products visible)
|
||||
- Infinite scroll with memory concerns
|
||||
- Performance issues with many DOM elements
|
||||
|
||||
**How it works:**
|
||||
- Only render visible products + buffer
|
||||
- Reuse DOM elements as user scrolls
|
||||
- Maintains scroll position
|
||||
- Libraries: react-window, react-virtuoso
|
||||
|
||||
**Tradeoff:**
|
||||
- Complex implementation
|
||||
- Better performance for large lists
|
||||
- Required for catalogs with 1000+ products loaded
|
||||
|
||||
### Filter Performance
|
||||
|
||||
**Optimistic UI:**
|
||||
- Update grid immediately (predicted results)
|
||||
- Show loading overlay briefly
|
||||
- Replace with real results
|
||||
- Better perceived performance
|
||||
|
||||
## Mobile Optimization
|
||||
|
||||
**Critical mobile patterns:**
|
||||
|
||||
**2-column grid:**
|
||||
- Maximum 2 products per row
|
||||
- Larger touch targets
|
||||
- Simplified cards (essential info only)
|
||||
- Remove hover effects
|
||||
|
||||
**Filter drawer:**
|
||||
- Full-screen or 80% width drawer
|
||||
- "Filters" button with badge count
|
||||
- Batch apply (don't re-fetch on each change)
|
||||
- Clear all at top
|
||||
|
||||
**Sticky filter/sort bar:**
|
||||
- Fixed at top while scrolling
|
||||
- Quick access to filters and sorting
|
||||
- Shows active filter count
|
||||
- Higher engagement rates
|
||||
|
||||
**Infinite scroll default:**
|
||||
- Better mobile UX than pagination
|
||||
- Natural scrolling behavior
|
||||
- Keep pagination URLs for SEO
|
||||
- Handle back button correctly
|
||||
|
||||
**Performance:**
|
||||
- Lazy load images (critical on mobile)
|
||||
- Limit initial products (12-24)
|
||||
- Optimize image sizes for mobile
|
||||
- Fast filter updates (<1s)
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential product listing features:**
|
||||
|
||||
- [ ] **RECOMMENDED: Product listing built as reusable component**
|
||||
- [ ] Reusable component works for: shop all, category pages, search results, sale pages
|
||||
- [ ] Component accepts filter parameters (categoryId, searchQuery, promotionId, etc.)
|
||||
- [ ] Responsive grid (3-4 columns desktop, 2 mobile)
|
||||
- [ ] Decision made: Pagination vs infinite scroll vs load more
|
||||
- [ ] Filter pattern selected: Sidebar (desktop) vs drawer (mobile)
|
||||
- [ ] Filters fetched from backend dynamically
|
||||
- [ ] Filter options show product count
|
||||
- [ ] Active filters displayed above grid (removable pills)
|
||||
- [ ] "Clear all filters" button prominent
|
||||
- [ ] Sorting options (featured, price, newest, bestselling)
|
||||
- [ ] Sort updates products without clearing filters
|
||||
- [ ] Filters and sort persist in URL (shareable)
|
||||
- [ ] Results count displayed ("Showing 1-24 of 156 products")
|
||||
- [ ] Empty state: "No products match filters" with suggestions
|
||||
- [ ] "Clear all filters" prominent when no results
|
||||
- [ ] Product prices displayed correctly (Medusa: as-is, not divided)
|
||||
- [ ] Lazy loading for images (Intersection Observer)
|
||||
- [ ] Loading state for filter changes (< 1s)
|
||||
- [ ] Mobile: Filter drawer with batch apply
|
||||
- [ ] Mobile: 2-column grid maximum
|
||||
- [ ] Mobile: Sticky filter/sort button
|
||||
- [ ] Pagination URLs for SEO (even with infinite scroll)
|
||||
- [ ] Back button support (restore filters, scroll position)
|
||||
- [ ] Keyboard accessible (tab through filters, enter to apply)
|
||||
- [ ] ARIA labels on filters (role="group", aria-label)
|
||||
@@ -0,0 +1,356 @@
|
||||
# Static Pages
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [FAQ Page](#faq-page)
|
||||
- [About Page](#about-page)
|
||||
- [Contact Page](#contact-page)
|
||||
- [Shipping and Returns](#shipping-and-returns)
|
||||
- [Privacy Policy and Terms](#privacy-policy-and-terms)
|
||||
- [Size Guide](#size-guide)
|
||||
- [Mobile and SEO](#mobile-and-seo)
|
||||
- [Checklist](#checklist)
|
||||
|
||||
## Overview
|
||||
|
||||
Static pages provide essential information about the store, policies, and customer support. Purpose: Build trust, reduce support inquiries, meet legal requirements, improve SEO.
|
||||
|
||||
### Essential Static Pages
|
||||
|
||||
**Required:**
|
||||
- Privacy Policy (legally required in most regions)
|
||||
- Terms and Conditions
|
||||
- Shipping and Returns
|
||||
- Contact
|
||||
|
||||
**Strongly recommended:**
|
||||
- FAQ (Frequently Asked Questions)
|
||||
- About Us
|
||||
|
||||
**Optional:**
|
||||
- Size Guide (for apparel stores)
|
||||
- Store Locator (if physical stores)
|
||||
|
||||
## FAQ Page
|
||||
|
||||
### Purpose and Structure
|
||||
|
||||
**Purpose**: Answer common customer questions, reduce support inquiries, improve purchase confidence.
|
||||
|
||||
**Common FAQ categories:**
|
||||
- Ordering and Payment
|
||||
- Shipping and Delivery
|
||||
- Returns and Exchanges
|
||||
- Product Information
|
||||
- Account Management
|
||||
|
||||
### Layout Pattern: Accordion (Recommended)
|
||||
|
||||
Question as clickable header, answer hidden by default, click to expand. Compact, scannable format.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Frequently Asked Questions
|
||||
|
||||
Ordering and Payment
|
||||
|
||||
▸ How do I place an order?
|
||||
▸ What payment methods do you accept?
|
||||
▸ Is it safe to use my credit card?
|
||||
|
||||
Shipping and Delivery
|
||||
|
||||
▸ How long does shipping take?
|
||||
▸ Do you ship internationally?
|
||||
```
|
||||
|
||||
**Alternative: All Expanded**
|
||||
All questions and answers visible. Better for few questions (<10), good for SEO (all content visible), easy to Ctrl+F search.
|
||||
|
||||
### Search Functionality
|
||||
|
||||
**FAQ search** (for extensive FAQs):
|
||||
Search box at top, real-time filtering as user types, highlights matching questions, "No results" state with contact link.
|
||||
|
||||
### Content Guidelines
|
||||
|
||||
**Question format:**
|
||||
Clear, concise, use customer language, start with question words (How, What, When).
|
||||
|
||||
**Answer format:**
|
||||
Direct answer first sentence, additional details if needed, bullet points for lists, link to related pages, 2-4 sentences ideal.
|
||||
|
||||
## About Page
|
||||
|
||||
### Purpose and Content
|
||||
|
||||
**Purpose**: Tell brand story, build trust and connection, showcase values and mission, differentiate from competitors.
|
||||
|
||||
**Key sections:**
|
||||
- Brand story/history (how the company started)
|
||||
- Mission and values (3-5 core values)
|
||||
- Why choose us (what makes you different)
|
||||
- Sustainability/social responsibility (if applicable)
|
||||
|
||||
### Layout Structure
|
||||
|
||||
**Hero section:**
|
||||
Large image (team, products, brand imagery), headline (brand tagline or mission), brief intro paragraph (2-3 sentences).
|
||||
|
||||
**Story section:**
|
||||
3-5 paragraphs, conversational tone, focus on customer benefits.
|
||||
|
||||
**Values section:**
|
||||
3-5 core values with icon or image for each, brief description (1-2 sentences).
|
||||
|
||||
**Call-to-action:**
|
||||
Shop products, join newsletter, follow on social media.
|
||||
|
||||
## Contact Page
|
||||
|
||||
### Contact Methods
|
||||
|
||||
**Essential:**
|
||||
- Contact form (primary)
|
||||
- Email address
|
||||
- Phone number (optional)
|
||||
- Business hours
|
||||
- Response time expectation ("We respond within 24 hours")
|
||||
|
||||
**Optional:**
|
||||
- Live chat button
|
||||
- FAQ link ("Find answers faster")
|
||||
- Social media links
|
||||
- Physical address (if applicable)
|
||||
|
||||
### Contact Form
|
||||
|
||||
**Form fields:**
|
||||
- Name (required)
|
||||
- Email (required)
|
||||
- Subject or Topic (dropdown, optional)
|
||||
- Message (textarea, required)
|
||||
- Order number (optional, for order inquiries)
|
||||
- Submit button
|
||||
|
||||
**Form features:**
|
||||
Clear field labels, placeholder examples, required field indicators, email validation, success confirmation.
|
||||
|
||||
## Shipping and Returns
|
||||
|
||||
### Shipping Information
|
||||
|
||||
**Key sections:**
|
||||
- Shipping methods and costs (table format)
|
||||
- Delivery timeframes
|
||||
- International shipping (if applicable)
|
||||
- Order processing time ("Orders placed by 2pm EST ship same day")
|
||||
- Tracking information
|
||||
- Shipping restrictions
|
||||
|
||||
**Shipping Methods Table Format:**
|
||||
```
|
||||
Method | Cost | Delivery Time
|
||||
──────────────────────────────────────────
|
||||
Standard | $5.99 | 5-7 business days
|
||||
Express | $12.99 | 2-3 business days
|
||||
Overnight | $24.99 | Next business day
|
||||
Free Shipping | Free | Orders over $50
|
||||
```
|
||||
|
||||
### Returns and Exchanges
|
||||
|
||||
**Key information:**
|
||||
- Return window (e.g., 30 days)
|
||||
- Return conditions (unused, tags attached, etc.)
|
||||
- Refund method (original payment, store credit)
|
||||
- Return shipping cost
|
||||
- Exchange process
|
||||
- Non-returnable items
|
||||
|
||||
**Return process steps:**
|
||||
```
|
||||
How to Return an Item
|
||||
|
||||
1. Initiate Return
|
||||
Log into your account and select the order
|
||||
|
||||
2. Print Return Label
|
||||
We'll email you a prepaid shipping label
|
||||
|
||||
3. Pack and Ship
|
||||
Include all original packaging and tags
|
||||
|
||||
4. Receive Refund
|
||||
Refunds processed within 5-7 business days
|
||||
```
|
||||
|
||||
## Privacy Policy and Terms
|
||||
|
||||
### Privacy Policy
|
||||
|
||||
**Purpose**: Legal requirement in most regions (GDPR, CCPA compliance), explain data collection and use, build customer trust.
|
||||
|
||||
**Key sections:**
|
||||
- Information collected
|
||||
- How information is used
|
||||
- Data sharing and disclosure
|
||||
- Cookies and tracking
|
||||
- User rights (access, deletion, etc.)
|
||||
- Data security measures
|
||||
- Contact for privacy inquiries
|
||||
- Last updated date
|
||||
|
||||
**Layout:**
|
||||
Table of contents (for long policies), clear section headings, numbered or bulleted lists, plain language, last updated date at top.
|
||||
|
||||
**Important**: Consult legal counsel for content, include required disclosures, update regularly.
|
||||
|
||||
### Terms and Conditions
|
||||
|
||||
**Purpose**: Legal agreement between store and customer, define rules and limitations, protect business legally.
|
||||
|
||||
**Key sections:**
|
||||
- Acceptance of terms
|
||||
- Product descriptions and pricing
|
||||
- Order acceptance and cancellation
|
||||
- Payment and billing
|
||||
- Shipping and delivery
|
||||
- Returns and refunds
|
||||
- Intellectual property
|
||||
- Limitation of liability
|
||||
- Dispute resolution
|
||||
- Changes to terms
|
||||
|
||||
**Layout:**
|
||||
Numbered sections (1, 1.1, 1.2), table of contents for long documents, clear section titles, anchor links to sections.
|
||||
|
||||
## Size Guide
|
||||
|
||||
**Purpose (for apparel/footwear stores)**:
|
||||
Help customers choose correct size, reduce returns due to sizing issues, increase purchase confidence.
|
||||
|
||||
**Content:**
|
||||
- Size charts (numeric measurements) - use proper table markup
|
||||
- How to measure instructions with illustrations
|
||||
- Fit descriptions (slim fit, relaxed, etc.)
|
||||
- Model measurements (for reference)
|
||||
- Size conversion chart (US, EU, UK)
|
||||
|
||||
**Size Chart Format:**
|
||||
```
|
||||
Women's Tops Size Guide
|
||||
|
||||
Size | Bust | Waist | Hips
|
||||
─────────────────────────────────────
|
||||
XS | 32-33" | 24-25" | 35-36"
|
||||
S | 34-35" | 26-27" | 37-38"
|
||||
M | 36-37" | 28-29" | 39-40"
|
||||
L | 38-40" | 30-32" | 41-43"
|
||||
XL | 41-43" | 33-35" | 44-46"
|
||||
```
|
||||
|
||||
**Accessibility:**
|
||||
Use proper table markup (not images), clear column headers, screen reader friendly, mobile-responsive tables.
|
||||
|
||||
## Mobile and SEO
|
||||
|
||||
### Mobile Optimizations
|
||||
|
||||
**Layout:**
|
||||
Single column, full-width content, larger touch targets for accordions, generous padding (16-20px).
|
||||
|
||||
**Typography:**
|
||||
16px minimum body text, 24-32px headings, line height 1.5-1.6, short paragraphs (3-4 sentences max).
|
||||
|
||||
**Tables:**
|
||||
Horizontal scroll for wide tables or card layout (stacked rows), responsive design.
|
||||
|
||||
**Forms:**
|
||||
Full-width inputs, 44-48px height, large submit buttons, appropriate keyboard types.
|
||||
|
||||
**Quick actions:**
|
||||
- Tap-to-call: Phone numbers as clickable links (`tel:`)
|
||||
- Tap-to-email: Email addresses as clickable links (`mailto:`)
|
||||
- Map integration: "Get Directions" links to native map app
|
||||
|
||||
### SEO for Static Pages
|
||||
|
||||
**On-Page SEO:**
|
||||
- Unique title per page (50-60 characters max, format: "Page Title | Store Name")
|
||||
- Meta descriptions (150-160 characters, include call-to-action)
|
||||
- Proper heading hierarchy (one H1 per page, H2 for sections, H3 for subsections)
|
||||
- Original, unique content
|
||||
- Internal links to products/categories
|
||||
- Regular updates (especially FAQ)
|
||||
|
||||
**Schema Markup:**
|
||||
- FAQ schema for FAQ pages (rich snippets)
|
||||
- Organization schema for About page
|
||||
- LocalBusiness schema for Store Locator
|
||||
- ContactPoint schema for Contact page
|
||||
|
||||
**Benefits:**
|
||||
Rich snippets in search results, improved visibility, better click-through rates.
|
||||
|
||||
## Checklist
|
||||
|
||||
**Essential pages:**
|
||||
|
||||
- [ ] FAQ page with accordion layout
|
||||
- [ ] FAQ search functionality (for extensive FAQs)
|
||||
- [ ] FAQ categories organized logically
|
||||
- [ ] Contact page with form
|
||||
- [ ] Contact form validation
|
||||
- [ ] Email address and business hours visible
|
||||
- [ ] Shipping and Returns page
|
||||
- [ ] Shipping methods and costs table
|
||||
- [ ] Delivery timeframes clear
|
||||
- [ ] Return policy with conditions
|
||||
- [ ] Return process step-by-step
|
||||
- [ ] Privacy Policy page
|
||||
- [ ] Last updated date on Privacy Policy
|
||||
- [ ] Privacy policy in plain language
|
||||
- [ ] Terms and Conditions page
|
||||
- [ ] Last updated date on Terms
|
||||
|
||||
**Optional but valuable:**
|
||||
|
||||
- [ ] About Us page with brand story
|
||||
- [ ] Mission and values section
|
||||
- [ ] Size Guide (if apparel)
|
||||
- [ ] Size charts with measurements
|
||||
- [ ] How to measure instructions
|
||||
- [ ] Store Locator (if physical stores)
|
||||
|
||||
**SEO and technical:**
|
||||
|
||||
- [ ] Unique title tags per page
|
||||
- [ ] Meta descriptions per page
|
||||
- [ ] Proper heading hierarchy (H1, H2, H3)
|
||||
- [ ] Internal links to products/categories
|
||||
- [ ] Schema markup (FAQ, Organization, etc.)
|
||||
- [ ] Mobile-responsive layout
|
||||
- [ ] Fast loading times
|
||||
|
||||
**Accessibility:**
|
||||
|
||||
- [ ] Semantic HTML (main, article, section)
|
||||
- [ ] ARIA labels on accordions
|
||||
- [ ] Keyboard navigation supported
|
||||
- [ ] Focus indicators visible
|
||||
- [ ] High contrast text (4.5:1)
|
||||
- [ ] Forms properly labeled
|
||||
- [ ] Tables with proper headers
|
||||
- [ ] Alt text on images
|
||||
|
||||
**Content quality:**
|
||||
|
||||
- [ ] Clear, concise writing
|
||||
- [ ] Short paragraphs (3-4 sentences)
|
||||
- [ ] Bullet points for lists
|
||||
- [ ] Regular content updates
|
||||
- [ ] No outdated information
|
||||
- [ ] Contact info current
|
||||
- [ ] Policies reflect current practices
|
||||
307
.agents/skills/storefront-best-practices/reference/medusa.md
Normal file
307
.agents/skills/storefront-best-practices/reference/medusa.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# Medusa Backend Integration
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Installation](#installation)
|
||||
- [SDK Setup](#sdk-setup)
|
||||
- [Vite Configuration](#vite-configuration-tanstack-start-vite-projects)
|
||||
- [TypeScript Types](#typescript-types)
|
||||
- [Price Display](#price-display)
|
||||
- [SDK Organization](#sdk-organization)
|
||||
- [Critical Medusa Patterns](#critical-medusa-patterns)
|
||||
- [Region State Management](#region-state-management)
|
||||
|
||||
## Overview
|
||||
|
||||
Guide for connecting your storefront to Medusa backend using the [Medusa JS SDK](https://docs.medusajs.com/resources/js-sdk).
|
||||
|
||||
**When to use this guide:**
|
||||
- Building a storefront with Medusa backend
|
||||
- Need to integrate Medusa SDK properly
|
||||
- Working with multi-region stores
|
||||
- Handling Medusa-specific pricing and regions
|
||||
|
||||
**For general backend patterns**, see `reference/connecting-to-backend.md`.
|
||||
|
||||
## ⚠️ CRITICAL: Follow the 5-Step Verification Workflow
|
||||
|
||||
**BEFORE writing code that calls Medusa SDK methods**, follow the mandatory workflow from SKILL.md:
|
||||
|
||||
1. **PAUSE** - Don't write code yet
|
||||
2. **QUERY** MCP server or docs (https://docs.medusajs.com/resources/js-sdk) for exact method
|
||||
3. **VERIFY** with user what you found
|
||||
4. **WRITE** code using verified method
|
||||
5. **CHECK** for TypeScript errors - Type errors mean wrong method name or parameters
|
||||
|
||||
**If you see TypeScript errors on SDK methods, you used incorrect methods. Go back to Step 2 and verify again.**
|
||||
|
||||
**This file shows PATTERNS (what to do), not exact methods (how to do it). Always verify method names with MCP/docs before use.**
|
||||
|
||||
## 💡 RECOMMENDED: Set Up Medusa MCP Server
|
||||
|
||||
**If the Medusa MCP server is not installed, strongly recommend setting it up.**
|
||||
|
||||
**Setup instructions**: add HTTP MCP server with URL https://docs.medusajs.com/mcp
|
||||
|
||||
The MCP server provides real-time method verification without leaving your IDE.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @medusajs/js-sdk@latest @medusajs/types@latest
|
||||
```
|
||||
|
||||
Both required: SDK provides functionality, types provide TypeScript support.
|
||||
|
||||
## SDK Setup
|
||||
|
||||
```typescript
|
||||
import Medusa from "@medusajs/js-sdk"
|
||||
|
||||
export const sdk = new Medusa({
|
||||
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL || "http://localhost:9000",
|
||||
debug: process.env.NODE_ENV === "development",
|
||||
publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
|
||||
})
|
||||
```
|
||||
|
||||
**CRITICAL: Always set publishableKey.**
|
||||
|
||||
- Required for multi-region stores to get correct pricing
|
||||
- Required for accessing products with regional prices
|
||||
- Without it, product queries may fail or return incorrect prices
|
||||
- Get publishable key from Medusa admin dashboard under Settings → Publishable API Keys
|
||||
|
||||
**IMPORTANT: Storefront Port Configuration**
|
||||
|
||||
- **Run storefront at port 8000** to avoid CORS errors
|
||||
- Medusa backend's default CORS configuration expects storefront at `http://localhost:8000`
|
||||
- If using different port, configure CORS in Medusa backend's `medusa-config.ts`:
|
||||
```typescript
|
||||
store_cors: process.env.STORE_CORS || "http://localhost:YOUR_PORT"
|
||||
```
|
||||
- Common framework defaults:
|
||||
- Next.js: Port 3000 (needs CORS config update)
|
||||
- TanStack Start: Port 3000 (needs CORS config update)
|
||||
- Vite: Port 5173 (needs CORS config update)
|
||||
- **Recommended**: Use port 8000 to avoid configuration changes
|
||||
|
||||
## Vite Configuration (TanStack Start, Vite Projects)
|
||||
|
||||
**IMPORTANT: For Vite-based projects, configure SSR externals.**
|
||||
|
||||
Add this to your `vite.config.ts`:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
// ... other config
|
||||
ssr: {
|
||||
noExternal: ['@medusajs/js-sdk'],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Why this is needed:**
|
||||
- Medusa JS SDK must be processed by Vite during SSR
|
||||
- Without this config, SDK calls will fail during server-side rendering
|
||||
- Applies to TanStack Start, vanilla Vite, and other Vite-based frameworks
|
||||
|
||||
## TypeScript Types
|
||||
|
||||
**IMPORTANT: Always use `@medusajs/types` - never define custom types.**
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
StoreProduct,
|
||||
StoreCart,
|
||||
StoreCartLineItem,
|
||||
StoreRegion,
|
||||
StoreProductCategory,
|
||||
StoreCustomer,
|
||||
StoreOrder
|
||||
} from "@medusajs/types"
|
||||
```
|
||||
|
||||
**Why use official types:**
|
||||
- Complete and accurate type definitions
|
||||
- Updated with each Medusa release
|
||||
- Includes all entity relationships and fields
|
||||
- Prevents type mismatches with API responses
|
||||
|
||||
## Price Display
|
||||
|
||||
**CRITICAL: Medusa prices are stored as-is - DO NOT divide by 100.**
|
||||
|
||||
Unlike Stripe (where amounts are in cents), Medusa stores prices in their display value.
|
||||
|
||||
```typescript
|
||||
// ❌ WRONG - Dividing by 100
|
||||
<div>${product.variants[0].prices[0].amount / 100}</div>
|
||||
|
||||
// ✅ CORRECT - Display as-is
|
||||
<div>${product.variants[0].prices[0].amount}</div>
|
||||
```
|
||||
|
||||
**Correct price formatting:**
|
||||
```typescript
|
||||
const formatPrice = (amount: number, currencyCode: string) => {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: currencyCode,
|
||||
}).format(amount)
|
||||
}
|
||||
```
|
||||
|
||||
**Price fields to use:**
|
||||
- `variant.calculated_price.calculated_amount` - Final price including promotions
|
||||
- `variant.calculated_price.original_amount` - Original price before discounts
|
||||
- Both are already in display format - no conversion needed
|
||||
|
||||
## SDK Organization
|
||||
|
||||
The Medusa SDK is organized by resources:
|
||||
- `sdk.store.product.*` - Product operations
|
||||
- `sdk.store.cart.*` - Cart operations
|
||||
- `sdk.store.category.*` - Category operations
|
||||
- `sdk.store.customer.*` - Customer operations (authenticated)
|
||||
- `sdk.store.order.*` - Order operations (authenticated)
|
||||
- `sdk.store.payment.*` - Payment operations
|
||||
- `sdk.store.fulfillment.*` - Shipping/fulfillment operations
|
||||
- `sdk.store.region.*` - Region operations
|
||||
|
||||
**To find specific methods**: Consult documentation (https://docs.medusajs.com/resources/js-sdk) or use MCP server.
|
||||
|
||||
## Critical Medusa Patterns
|
||||
|
||||
**IMPORTANT**: The patterns below show WHAT to do, not exact HOW. Always verify method names and signatures with MCP server or documentation before using.
|
||||
|
||||
### 1. Always Pass `region_id` for Products
|
||||
|
||||
**Pattern**: Product queries require `region_id` parameter for correct pricing.
|
||||
|
||||
**Why:** Without `region_id`, `calculated_price` will be missing or incorrect.
|
||||
|
||||
**To implement**: Query MCP/docs for product listing and retrieval methods. Pass `region_id: selectedRegion.id` as parameter.
|
||||
|
||||
### 2. Cart Updates Pattern
|
||||
|
||||
**Pattern**: Line items have dedicated methods (create, update, delete). Other cart properties use a generic update method.
|
||||
|
||||
**Line item operations** (verify exact method names with MCP/docs):
|
||||
- Add item to cart
|
||||
- Update item quantity
|
||||
- Remove item from cart
|
||||
|
||||
**Other cart updates** (email, addresses, region, promo codes):
|
||||
- Use cart's generic update method
|
||||
|
||||
**To implement**: Query MCP server or documentation for exact cart method signatures:
|
||||
https://docs.medusajs.com/resources/references/js-sdk/store/cart
|
||||
|
||||
### 3. Payment Flow Pattern
|
||||
|
||||
**High-level workflow:**
|
||||
1. Query available payment providers for the cart's region
|
||||
2. User selects payment method
|
||||
3. Initialize payment session for selected provider
|
||||
4. Render provider-specific UI (Stripe Elements, etc.)
|
||||
5. Complete payment through provider
|
||||
|
||||
**To implement**: Query MCP/docs for:
|
||||
- Payment provider listing method
|
||||
- Payment session initialization method
|
||||
- Payment completion method
|
||||
|
||||
**Resources**:
|
||||
- MCP server (if installed)
|
||||
- Medusa payment docs: https://docs.medusajs.com/resources/references/js-sdk/store/payment
|
||||
- `reference/layouts/checkout.md` for checkout flow
|
||||
|
||||
### 4. Checkout Flow Pattern
|
||||
|
||||
**High-level workflow:**
|
||||
1. Collect shipping address
|
||||
2. Query available shipping options for cart
|
||||
3. User selects shipping method
|
||||
4. Collect payment information
|
||||
5. Initialize payment session
|
||||
6. Complete/place order
|
||||
|
||||
**To implement**: Query MCP/docs for each step's methods. Don't guess method names.
|
||||
|
||||
### 5. Category Fetching
|
||||
|
||||
**Pattern**: Fetch categories from `sdk.store.category.*` resource.
|
||||
|
||||
**To implement**: Query MCP/docs for category listing method. See `reference/components/navbar.md` for usage patterns.
|
||||
|
||||
## Region State Management
|
||||
|
||||
**Critical for Medusa**: Region determines currency, pricing, taxes, and available products.
|
||||
|
||||
### Why Region Context Matters
|
||||
|
||||
Medusa requires region for:
|
||||
- Creating carts (must pass `region_id`)
|
||||
- Retrieving products with correct prices
|
||||
- Determining currency and tax calculations
|
||||
- Filtering available payment and shipping methods
|
||||
|
||||
### Implementation Approach
|
||||
|
||||
**High-level workflow:**
|
||||
1. Fetch available regions on app load (query MCP/docs for region listing method)
|
||||
2. Detect user's country (IP, browser locale, or user selection)
|
||||
3. Find region containing that country
|
||||
4. Store selected region globally (React Context, Zustand, etc.)
|
||||
5. Use `selectedRegion.id` for all cart and product operations
|
||||
|
||||
**When user changes country:**
|
||||
- Find new region containing the country
|
||||
- Update cart with new region_id (query MCP/docs for cart update method)
|
||||
- Store selection in localStorage for persistence
|
||||
|
||||
**To implement**: Query MCP server or docs for exact region and cart methods. Don't copy example code without verification.
|
||||
|
||||
**For detailed region implementation with code examples**, see:
|
||||
- `reference/components/country-selector.md`
|
||||
- Medusa MCP server (if installed)
|
||||
- Medusa docs: https://docs.medusajs.com/resources/storefront-development/regions/context
|
||||
|
||||
## Error Handling
|
||||
|
||||
SDK throws `FetchError` with:
|
||||
- `status`: HTTP status code
|
||||
- `statusText`: Error code
|
||||
- `message`: Descriptive message
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const data = await sdk.store.customer.retrieve()
|
||||
} catch (error) {
|
||||
const fetchError = error as FetchError
|
||||
if (fetchError.statusText === "Unauthorized") {
|
||||
redirect('/login')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Endpoints
|
||||
|
||||
For custom API routes:
|
||||
|
||||
```typescript
|
||||
const data = await sdk.client.fetch(`/custom/endpoint`, {
|
||||
method: "POST",
|
||||
body: { /* ... */ },
|
||||
})
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- **Medusa JS SDK docs**: https://docs.medusajs.com/resources/js-sdk
|
||||
- **Storefront development**: https://docs.medusajs.com/resources/storefront-development
|
||||
- **Checkout flow**: https://docs.medusajs.com/resources/storefront-development/checkout
|
||||
- **Region context**: https://docs.medusajs.com/resources/storefront-development/regions/context
|
||||
- **Use Medusa MCP server** if available for real-time method lookup
|
||||
@@ -0,0 +1,183 @@
|
||||
# Mobile Responsiveness for Ecommerce Storefronts
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Mobile Ecommerce Patterns](#mobile-ecommerce-patterns)
|
||||
- [Touch-Friendly Interactions](#touch-friendly-interactions)
|
||||
- [Mobile Performance](#mobile-performance)
|
||||
- [Safe Area Insets (iOS)](#safe-area-insets-ios)
|
||||
- [Common Mobile Mistakes](#common-mobile-mistakes)
|
||||
|
||||
## Overview
|
||||
|
||||
Over 60% of ecommerce traffic is mobile. Mobile-first design is essential for conversion.
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- Mobile-first CSS (min-width media queries)
|
||||
- 44x44px minimum touch targets
|
||||
- Sticky header with cart access
|
||||
- Large form inputs (48px height minimum)
|
||||
- Optimized images for mobile
|
||||
- Fast loading (LCP < 2.5s)
|
||||
|
||||
**Assumed knowledge**: AI agents already know mobile-first design principles, breakpoints, and responsive CSS. This guide focuses on ecommerce-specific mobile patterns.
|
||||
|
||||
## Mobile Ecommerce Patterns
|
||||
|
||||
### Sticky Elements (Critical for Conversion)
|
||||
|
||||
**Cart access always visible:**
|
||||
- Sticky header with cart icon (top-right)
|
||||
- Or: Sticky bottom navigation with cart
|
||||
- Never hide cart in hamburger drawer
|
||||
- Shows count badge, updates in real-time
|
||||
|
||||
**Sticky "Add to Cart" bar (product pages):**
|
||||
- Fixed at bottom of screen
|
||||
- Shows: Price + "Add to Cart" button
|
||||
- Appears after scrolling past fold
|
||||
- Always accessible without scrolling
|
||||
- **CRITICAL: Must use `env(safe-area-inset-bottom)` for iOS devices** (see Safe Area Insets section)
|
||||
- Significantly higher conversion rates
|
||||
|
||||
### Mobile Navigation Patterns
|
||||
|
||||
**Bottom navigation (optional pattern):**
|
||||
- Consider for mobile-heavy stores (>70% mobile traffic)
|
||||
- 4-5 primary actions: Home, Categories, Cart, Account, Search
|
||||
- Fixed at bottom (easier thumb access)
|
||||
- Icons + labels for clarity
|
||||
|
||||
**When to use:**
|
||||
- Mobile-first brands (fashion, beauty)
|
||||
- Younger demographic (18-34)
|
||||
- App-like experience desired
|
||||
|
||||
**When NOT to use:**
|
||||
- Desktop-heavy traffic
|
||||
- Complex navigation needs (>5 items)
|
||||
- B2B stores (desktop-focused)
|
||||
|
||||
### Mobile Product Browsing
|
||||
|
||||
**Image galleries:**
|
||||
- Full-width swipeable carousel
|
||||
- Pinch to zoom
|
||||
- Tap to open full-screen view
|
||||
- Dot indicators (1/5, 2/5)
|
||||
|
||||
**Filter drawer:**
|
||||
- "Filters" button with badge count (e.g., "Filters (3)")
|
||||
- Slide-out drawer (full-screen or 80% width)
|
||||
- Accordion sections for filter categories
|
||||
- "Apply" button at bottom (batch filtering)
|
||||
- "Clear All" option at top
|
||||
|
||||
**Why batch filtering on mobile:**
|
||||
- Prevents multiple re-renders on slow connections
|
||||
- User adjusts multiple filters before applying
|
||||
- Less disruptive mobile UX
|
||||
|
||||
### Mobile Checkout Optimization
|
||||
|
||||
**Digital wallets priority (CRITICAL for mobile conversion):**
|
||||
- Apple Pay / Google Pay buttons prominent at top (if supported in ecommerce backend)
|
||||
- Can improve mobile checkout conversion by 20-40%
|
||||
- One-click payment with pre-filled shipping addresses (if supported in ecommerce backend)
|
||||
- Consider making digital wallet the default on mobile
|
||||
|
||||
**Decision: Order summary placement**
|
||||
- Collapsible at top (recommended): Saves screen space for form, expandable for review
|
||||
- Fixed at bottom: Always visible but takes space from form
|
||||
- Use collapsible on mobile to prioritize form completion
|
||||
|
||||
**Form optimizations:**
|
||||
- Single-column layout (never multi-column on mobile)
|
||||
- 44-48px input height minimum
|
||||
- Proper keyboard types (`inputMode="email"`, `"numeric"`, `"tel"`)
|
||||
- Autocomplete attributes for autofill (`autocomplete="email"`, `"name"`, `"address-line1"`)
|
||||
- Consider single-page layout over multi-step (less friction on mobile)
|
||||
|
||||
## Touch-Friendly Interactions
|
||||
|
||||
**Standard touch targets:** 44x44px minimum for all interactive elements. Pay special attention to:
|
||||
- Filter checkboxes on product listings
|
||||
- Quantity +/- buttons on product pages
|
||||
- Small action buttons on product cards
|
||||
- Modal close buttons
|
||||
|
||||
**Swipe gestures for ecommerce:**
|
||||
- Product image galleries (critical - users expect swipeable images)
|
||||
- Related product sliders
|
||||
- Category carousels
|
||||
|
||||
**Mobile input optimization:**
|
||||
- 16px minimum font size for inputs (prevents iOS auto-zoom)
|
||||
- Proper `inputMode` attributes: `"email"`, `"numeric"`, `"tel"`
|
||||
- Autocomplete attributes: `autocomplete="email"`, `"name"`, `"address-line1"`
|
||||
|
||||
## Mobile Performance
|
||||
|
||||
**Ecommerce performance priorities:**
|
||||
|
||||
1. **Product images** (highest impact): Optimize for mobile (<500KB), lazy load below-fold, responsive images with appropriate sizes
|
||||
2. **Optimistic UI**: Cart count updates immediately, instant feedback on add to cart
|
||||
3. **Skeleton screens**: Show loading placeholders for product grids, not blank pages
|
||||
|
||||
**Critical mobile performance issues:**
|
||||
- Unoptimized product images (>1MB) - most common issue
|
||||
- Loading entire product catalog at once - use pagination or infinite scroll
|
||||
- Heavy analytics scripts on checkout - defer to post-purchase
|
||||
|
||||
**Target**: LCP < 2.5s, mobile-optimized images, server-side rendering for product pages
|
||||
|
||||
## Safe Area Insets (iOS)
|
||||
|
||||
Use `env(safe-area-inset-*)` to handle iOS notches and rounded corners on:
|
||||
- Sticky headers (top inset)
|
||||
- Sticky bottom navigation or add-to-cart bars (bottom inset)
|
||||
- Full-screen modals
|
||||
|
||||
**Critical for ecommerce**: Bottom "Add to Cart" bars will be cut off by iOS home indicator without bottom inset (~34px). Test on real iOS devices with notches.
|
||||
|
||||
## Common Mobile Mistakes
|
||||
|
||||
**Ecommerce-specific mobile issues:**
|
||||
|
||||
1. **Hiding cart in drawer** - Cart icon hidden in hamburger menu. Keep cart always visible in header (top-right).
|
||||
|
||||
2. **No sticky cart access** - Cart scrolls off screen on product pages. Use sticky header or sticky bottom "Add to Cart" bar.
|
||||
|
||||
3. **Desktop-sized images** - Serving 2MB+ product images to mobile. Use responsive images optimized for mobile (<500KB).
|
||||
|
||||
4. **Poor form experience** - Small inputs, wrong keyboards, no autocomplete. Use 48px inputs, proper `inputMode`, autocomplete attributes.
|
||||
|
||||
5. **Hover-only interactions** - Quick view, wishlist only work on hover. Add tap handlers, show on tap instead.
|
||||
|
||||
6. **Ignoring safe area insets** - Bottom "Add to Cart" bars cut off by iOS home indicator. Use `env(safe-area-inset-bottom)` for sticky bottom elements.
|
||||
|
||||
7. **No digital wallet options** - Missing Apple Pay/Google Pay on mobile checkout. Mobile users expect one-tap checkout options.
|
||||
|
||||
## Mobile Checklist
|
||||
|
||||
**Essential mobile optimizations:**
|
||||
|
||||
- [ ] Mobile-first CSS (min-width media queries)
|
||||
- [ ] 44x44px minimum touch targets throughout
|
||||
- [ ] Adequate spacing between interactive elements (8-16px)
|
||||
- [ ] Sticky header with cart icon (always visible)
|
||||
- [ ] Or: Sticky bottom "Add to Cart" bar on product pages
|
||||
- [ ] Large form inputs (48px height minimum)
|
||||
- [ ] Appropriate input types (`inputMode="email"`, `"numeric"`, `"tel"`)
|
||||
- [ ] Swipeable image galleries on product pages
|
||||
- [ ] Filter drawer with batch apply on product listings
|
||||
- [ ] Digital wallets prominent in checkout (Apple Pay, Google Pay)
|
||||
- [ ] Collapsible order summary in checkout
|
||||
- [ ] Optimized images for mobile (<500KB)
|
||||
- [ ] Lazy loading for below-fold content
|
||||
- [ ] Safe area insets for iOS notches (sticky elements)
|
||||
- [ ] 16px minimum font size (prevents iOS auto-zoom)
|
||||
- [ ] Test on real mobile devices (not just Chrome DevTools)
|
||||
- [ ] Core Web Vitals within targets (LCP < 2.5s, CLS < 0.1, INP < 200ms)
|
||||
195
.agents/skills/storefront-best-practices/reference/seo.md
Normal file
195
.agents/skills/storefront-best-practices/reference/seo.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# SEO Optimization for Ecommerce Storefronts
|
||||
|
||||
## Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Meta Tags Requirements](#meta-tags-requirements)
|
||||
- [Structured Data (Critical for Ecommerce)](#structured-data-critical-for-ecommerce)
|
||||
- [Ecommerce URL Patterns](#ecommerce-url-patterns)
|
||||
- [Product Page SEO](#product-page-seo)
|
||||
- [Duplicate Content Issues](#duplicate-content-issues)
|
||||
- [Dynamic Sitemaps](#dynamic-sitemaps)
|
||||
- [Common SEO Mistakes](#common-seo-mistakes)
|
||||
|
||||
## Overview
|
||||
|
||||
SEO is critical for ecommerce - organic search drives high-intent traffic. Proper implementation helps search engines understand products and enables rich results (star ratings, price, availability in search).
|
||||
|
||||
**Assumed knowledge**: AI agents know basic SEO (meta tags, Open Graph, Core Web Vitals). This guide focuses on ecommerce-specific patterns.
|
||||
|
||||
### Every Product Page Needs
|
||||
|
||||
- Unique title and description (product name + features)
|
||||
- Product schema with price, availability, rating
|
||||
- Breadcrumb schema (category hierarchy)
|
||||
- Canonical URL (prevents duplicate content)
|
||||
- Descriptive image alt text
|
||||
- Fast load time (LCP < 2.5s)
|
||||
|
||||
## Meta Tags Requirements
|
||||
|
||||
Generate unique meta tags for every product page dynamically from product data:
|
||||
|
||||
- **Title**: "Product Name - Key Feature | Store Name" (50-60 characters)
|
||||
- **Description**: Key features + USP (150-160 characters)
|
||||
- **Open Graph** tags for social sharing (image 1200x630px)
|
||||
- **Canonical URL** for variants and category paths
|
||||
|
||||
**Common mistake**: Same title/description across all products. Generate dynamically from product data.
|
||||
|
||||
## Structured Data (Critical for Ecommerce)
|
||||
|
||||
Enables rich results in search (star ratings, price, availability shown directly in search results).
|
||||
|
||||
### Product Schema (Required on All Product Pages)
|
||||
|
||||
Implement schema.org Product structured data with these critical fields:
|
||||
|
||||
**Essential fields:**
|
||||
- `name`, `description`, `image`, `sku`, `brand`
|
||||
- `offers` object with:
|
||||
- `price`: Current price (Medusa: use as-is; other backends: check format)
|
||||
- `priceCurrency`: ISO 4217 code (USD, EUR, GBP)
|
||||
- `availability`: Must accurately reflect real stock status (InStock, OutOfStock, PreOrder)
|
||||
- `priceValidUntil`: Required for Google Shopping (set 30+ days in future)
|
||||
|
||||
**Critical**: `availability` must be dynamic and accurate. Marking out-of-stock items as InStock violates Google's guidelines.
|
||||
|
||||
### AggregateRating Schema (When Reviews Exist)
|
||||
|
||||
Add `aggregateRating` object to Product schema when real reviews exist:
|
||||
- `ratingValue`: Average rating (e.g., "4.5")
|
||||
- `reviewCount`: Total number of reviews
|
||||
- `bestRating`: "5", `worstRating`: "1"
|
||||
|
||||
Displays star ratings in search results - powerful for CTR. **Only use for real reviews** - fake reviews violate guidelines.
|
||||
|
||||
### Breadcrumb Schema (Navigation Hierarchy)
|
||||
|
||||
Implement schema.org BreadcrumbList showing category hierarchy:
|
||||
- Home → Category → Product
|
||||
- Each level has `position`, `name`, `item` URL
|
||||
- Helps search engines understand site structure
|
||||
|
||||
### Organization Schema (Homepage Only)
|
||||
|
||||
Add on homepage only: Organization name, URL, logo, contact information. Helps establish brand identity in search.
|
||||
|
||||
## Ecommerce URL Patterns
|
||||
|
||||
**Product URLs**: Use readable slugs with hyphens (`/products/wireless-headphones-pro`). Include keywords naturally, keep short (<75 characters), never change URLs.
|
||||
|
||||
**Category URLs**: Choose consistent structure:
|
||||
- Hierarchical (`/categories/electronics/laptops`) for deep catalogs
|
||||
- Flat (`/categories/laptops`) for simpler management
|
||||
- Don't mix both approaches
|
||||
|
||||
**Pagination URLs**: Use query parameters (`/products?page=2`). Implement `rel="prev"` and `rel="next"` tags. Each page is canonical to itself (NOT to page 1) so all pages can be indexed.
|
||||
|
||||
**Filter URLs**: Use query parameters (`/products?color=blue&size=large`).
|
||||
|
||||
**Canonical decision for filters:**
|
||||
- Few filters (2-3): Index filtered pages (primary navigation)
|
||||
- Many filters (5+): Canonical to unfiltered (prevents duplicate content)
|
||||
- Popular combinations: Consider indexing separately
|
||||
|
||||
## Product Page SEO
|
||||
|
||||
**Title tags**: Pattern "Product Name - Key Feature | Store Name" (50-60 characters). Avoid generic titles or keyword stuffing.
|
||||
|
||||
**Meta descriptions**: Include 2-3 key features + USP (free shipping, returns, warranty) in 150-160 characters. Make it compelling.
|
||||
|
||||
**Image alt text**: Descriptive and specific. Describe what's visible, include product name and key visual attributes. Don't keyword stuff. Keep under 125 characters.
|
||||
|
||||
## Duplicate Content Issues
|
||||
|
||||
### Ecommerce Duplicate Content Challenges
|
||||
|
||||
**Common scenarios:**
|
||||
1. **Product variants**: Same product in multiple colors/sizes
|
||||
2. **Multiple categories**: Product listed in multiple categories
|
||||
3. **Filter combinations**: Filtered views create unique URLs
|
||||
4. **Sort parameters**: Sorted views create unique URLs
|
||||
|
||||
### Solution: Canonical URLs
|
||||
|
||||
**Variant handling:**
|
||||
- Choose one variant as canonical (usually default)
|
||||
- All other variants canonical to that one
|
||||
- Example: Blue, Red, Green shirts all canonical to Blue (default)
|
||||
|
||||
**Multiple category paths:**
|
||||
- Choose one category as canonical (usually primary category)
|
||||
- Example: Product in both "Electronics" and "Laptops" → canonical to "Laptops"
|
||||
|
||||
**Filtered/sorted views:**
|
||||
- Canonical to unfiltered, default-sorted page
|
||||
- Example: `/products?color=blue&sort=price` → canonical to `/products`
|
||||
|
||||
**Implementation:**
|
||||
```html
|
||||
<!-- On variant page (Red shirt) -->
|
||||
<link rel="canonical" href="https://yourstore.com/products/cotton-tshirt" />
|
||||
|
||||
<!-- On filtered page -->
|
||||
<link rel="canonical" href="https://yourstore.com/products" />
|
||||
```
|
||||
|
||||
## Dynamic Sitemaps
|
||||
|
||||
Generate sitemaps dynamically from database to help search engines discover all products and categories.
|
||||
|
||||
**Requirements:**
|
||||
- Include all public product and category pages
|
||||
- Update `lastModified` when products change (fetch from database)
|
||||
- Exclude `noindex` pages and filtered/sorted URLs
|
||||
- Split into multiple sitemaps if >50,000 URLs
|
||||
- Priority: Homepage (1.0) > Products (0.8) > Categories (0.6)
|
||||
|
||||
**Critical**: Regenerate sitemap when products are added/updated. Submit sitemap URL to Google Search Console.
|
||||
|
||||
## Common SEO Mistakes
|
||||
|
||||
**Ecommerce-specific SEO issues:**
|
||||
|
||||
1. **Duplicate content** - Same product accessible via multiple URLs (variants, categories). Use canonical URLs to consolidate signals.
|
||||
|
||||
2. **Missing Product schema** - No structured data on product pages. Implement Product schema for rich results (ratings, price in search).
|
||||
|
||||
3. **Incorrect availability status** - Marking out-of-stock items as "InStock" in schema. Dynamically set based on real stock levels (violates Google guidelines).
|
||||
|
||||
4. **Thin product content** - Only image and price, no description. Add detailed descriptions, specifications, reviews (200+ words).
|
||||
|
||||
5. **Static sitemap** - Never updates when products change. Generate dynamically from database so search engines discover new products.
|
||||
|
||||
6. **Poor image alt text** - Missing or generic "product image". Use descriptive alt text for image search traffic.
|
||||
|
||||
## SEO Checklist
|
||||
|
||||
### On Every Product Page
|
||||
|
||||
- [ ] Unique, descriptive title tag (50-60 characters)
|
||||
- [ ] Unique, compelling meta description (150-160 characters)
|
||||
- [ ] Open Graph and Twitter Card tags
|
||||
- [ ] Product schema with price, availability, rating (if reviews exist)
|
||||
- [ ] Breadcrumb schema (category hierarchy)
|
||||
- [ ] Descriptive alt text on all images
|
||||
- [ ] Canonical URL (especially for variants)
|
||||
- [ ] Fast load time (LCP < 2.5s)
|
||||
- [ ] Mobile-responsive design
|
||||
- [ ] Internal links to related products/categories
|
||||
- [ ] Detailed product description (200+ words ideal)
|
||||
|
||||
### Site-wide
|
||||
|
||||
- [ ] Dynamic XML sitemap submitted to search engines
|
||||
- [ ] Robots.txt properly configured
|
||||
- [ ] SSL certificate (HTTPS)
|
||||
- [ ] Mobile-friendly design (44px touch targets)
|
||||
- [ ] Organization schema on homepage
|
||||
- [ ] Proper heading hierarchy (H1 for product title)
|
||||
- [ ] Pagination implemented with rel="prev/next"
|
||||
- [ ] Canonical URLs for filtered/sorted pages
|
||||
- [ ] 404 pages with helpful navigation
|
||||
- [ ] Image optimization (WebP, lazy loading)
|
||||
- [ ] Core Web Vitals within targets (LCP < 2.5s, CLS < 0.1, INP < 200ms)
|
||||
Reference in New Issue
Block a user