Skip to content

Instantly share code, notes, and snippets.

@domitriusclark
Created October 10, 2025 21:41
Show Gist options
  • Select an option

  • Save domitriusclark/47778f9f9716aa9faf732e42c34f516b to your computer and use it in GitHub Desktop.

Select an option

Save domitriusclark/47778f9f9716aa9faf732e42c34f516b to your computer and use it in GitHub Desktop.
Ecommerce Recipe v2

Ecommerce Storefront Generation Recipe

Use as-is. Replace Inputs. Keep identifiers, paths, and events unchanged.

Inputs

Brand Name: "<YOUR BRAND NAME>"
Aesthetic Theme: "<YOUR AESTHETIC THEME>"
Reference Sites:
    - "<REF SITE 1>"
    - "<REF SITE 2>"
    - "<REF SITE 3>"

Generation Prompt

Project: {Brand Name} Stack: Astro 4 SSR + React 18 + TypeScript + TailwindCSS + Shopify Storefront API + Netlify Package Manager: npm

Design System - Aesthetic: {Aesthetic Theme} - References: {Reference Sites} - Auto-generate cohesive palette, fonts, visuals - Mobile-first; WCAG 2.1 AA

Critical Developer Experience - npm install && npm run dev works with no Shopify setup - Demo Mode: cart works; API failures log warnings only - Visual Indicator: bottom-left “Demo Mode” linking to SETUP.md when Shopify not configured - Docs: README.md (demo mode) + SETUP.md (Shopify setup)

Shopify Integration (Stubs) - src/lib/types.ts (import type): Money, ProductVariant, Product, Collection, CartLineItem, Cart - src/lib/shopify.ts (graceful errors): createCart(), addToCart(cartId, variantId, quantity), updateCartLines(), removeCartLines() - src/lib/cart.ts (Zustand + createJSONStorage) - State: cart, isLoading, error, isOpen - Actions: init(), add(variantId, quantity), updateQuantity(lineId, quantity), remove(lineId), clear(), clearError() - UI: openCart(), closeCart(), toggleCart() - Hooks: useCartCount(), useCartLoading(), useCartError() - Demo: local persistence; console warnings only

Cart Implementation (Exact Pattern) - CartDrawer.tsx: right drawer, backdrop, Esc handling, scroll lock - Header: button dispatches 'toggle-cart'; badge id="cart-count" - BaseLayout: include ; listen for 'toggle-cart' - ProductCard: variantId format ${product.id}-variant-default; no full-card link wrappers intercepting clicks; ensure overlay/button z-index allows clicks

Standard Architecture - Folders: components/layout, components/ui, components/cart, lib, pages, styles - Config: strict TypeScript; server output; Netlify adapter - Env: .env.example placeholders only; Shopify domain placeholder your-store.myshopify.com

Required Output - Repo runs immediately in demo mode; clear path to full Shopify integration

Canonical Anchors

BaseLayout.astro (DOMContentLoaded script) - dynamically import ../lib/cart - cartStore.init() - listen for 'toggle-cart' → cartStore.toggleCart() - subscribe to store → update element id="cart-count" (show “99+” if >99, hide when 0)

Header.astro - button calls global dispatchCartToggle() → dispatch CustomEvent('toggle-cart') - contains badge element id="cart-count" (initially hidden; shows when count > 0)

Root Include - at layout root

Demo Variant Convention - ProductCard uses variantId: ${product.id}-variant-default - createDemoVariant(variantId): returns complete ProductVariant with product info; productId = variantId.replace('-variant-default','')

Commands

  • Install: npm install
    
  • Develop: npm run dev
    
  • Build: npm run build && npm run preview
    
  • Typecheck (optional): npm run typecheck
    

Verification

  • Cart: add/update/remove; badge updates; drawer toggles; persists via localStorage
    
  • Demo Mode: indicator visible without Shopify env; API failures only warn in console
    
  • Accessibility/Responsive: backdrop, Esc close; mobile working
    
  • Build: npm run build succeeds
    

Constraints

  • Event name: 'toggle-cart'
    
  • Badge id: "cart-count"
    
  • VariantId format: `${product.id}-variant-default`
    
  • Keep specified file paths/names
    
  • Demo mode works without Shopify credentials
    
  • No user-facing errors in demo mode (console warnings only)
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment