vercel/commerce
Next.js Commerce
Renders product catalogs, shopping carts and checkouts for e-commerce stores
Product data flows from Shopify's GraphQL API through the shopifyFetch client into React Server Components that render product grids and details. When users interact with the cart, client components trigger server actions that update Shopify while useOptimistic immediately updates the UI. Search queries navigate to results pages where URL parameters drive product fetching and filtering.
Under the hood, the system uses 2 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.
A 7-component fullstack. 66 files analyzed. Data flows through 5 distinct pipeline stages.
How Data Flows Through the System
Product data flows from Shopify's GraphQL API through the shopifyFetch client into React Server Components that render product grids and details. When users interact with the cart, client components trigger server actions that update Shopify while useOptimistic immediately updates the UI. Search queries navigate to results pages where URL parameters drive product fetching and filtering.
- Load initial page data — Server components like Navbar and product pages call getMenu, getProducts, or getCollections which use shopifyFetch to query Shopify's GraphQL API with caching (config: SHOPIFY_STORE_DOMAIN, SHOPIFY_STOREFRONT_ACCESS_TOKEN)
- Render product catalog — Product data is mapped through Grid and GridTileImage components to create responsive product displays with images, prices, and hover effects [Product]
- Handle cart interactions — Cart components use useOptimistic to immediately update UI state while server actions like addItem, removeItem, and updateItemQuantity sync changes with Shopify [Product → CartItem]
- Process search and filtering — Search component captures user input and navigates to /search with query parameters, where server components fetch filtered products based on URL parameters
- Sync cart state — CartProvider loads cart from Shopify using cookie-stored cart ID, maintains optimistic state, and coordinates between server actions and UI updates [Cart → Cart]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
lib/shopify/types.tsobject with id: string, handle: string, title: string, description: string, availableForSale: boolean, variants: ProductVariant[], images: Image[], priceRange: {min/max: {amount: string, currencyCode: string}}, tags: string[]
Fetched from Shopify GraphQL API, cached with Next.js, rendered in product grids and detail pages, referenced when adding variants to cart
lib/shopify/types.tsobject with id: string, checkoutUrl: string, lines: CartItem[], totalQuantity: number, cost: {totalAmount: {amount: string, currencyCode: string}}
Retrieved from Shopify via cookie-stored cart ID, managed through server actions, optimistically updated in React context
lib/shopify/types.tsobject with id: string, quantity: number, cost: {totalAmount: {amount: string}}, merchandise: ProductVariant with nested product data
Created when products added to cart, updated via quantity changes, removed via server actions, immediately reflected through useOptimistic
lib/shopify/types.tsobject with id: string, handle: string, title: string, description: string, products: Product[], seo: {title: string, description: string}
Fetched from Shopify to populate category pages and navigation menus, cached and used for product organization
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
SHOPIFY_STOREFRONT_ACCESS_TOKEN environment variable exists and contains a valid token that won't expire during the app's lifetime
If this fails: If the token is missing, expired, or revoked, all product fetching silently fails or returns unauthorized errors, making the entire store non-functional
lib/shopify/index.ts:shopifyFetch
ProductVariant.price.amount is always a valid numeric string that can be parsed with Number() and won't contain currency symbols or formatting
If this fails: If price contains '$12.99' instead of '12.99', Number() returns NaN and cart totals become NaN, breaking checkout calculations
components/cart/cart-context.tsx:calculateItemCost
CartItem.merchandise.id matches the merchandiseId parameter format used by Shopify's API, and cart.lines array contains items with this exact structure
If this fails: If merchandise IDs have different formats or the cart structure changes, line items won't be found and removal operations silently fail, leaving stale items in cart
components/cart/actions.ts:removeItem
Shopify store has a menu handle named exactly 'next-js-frontend-header-menu' configured in the admin
If this fails: If the menu doesn't exist or is renamed, navigation returns empty array and the main menu disappears from the site without error
components/layout/navbar/index.tsx:getMenu
Next.js cache tags remain valid and cache invalidation happens immediately when products or cart data changes in Shopify
If this fails: If cache invalidation fails or is delayed, users see stale product prices, availability, or cart contents that don't match Shopify's current state
lib/shopify/index.ts:shopifyFetch
Product images from Shopify are reasonably sized and the Next.js Image component can handle them without memory issues in grid layouts
If this fails: If products have massive high-resolution images, the grid page becomes slow to load and may cause browser memory issues with many products displayed
components/grid/tile.tsx:GridTileImage
All items in the list array have either SortFilterItem shape (with slug/title) or PathFilterItem shape (with title/path), never mixed or undefined
If this fails: If list contains items with unexpected shapes or null values, the filter rendering breaks and users can't sort or filter products
components/layout/search/filter/index.tsx:FilterItemList
The cartPromise resolves before any cart operations (add/remove/update) are attempted by child components
If this fails: If cart operations fire while the initial cart is still loading, optimistic updates work but server actions may fail due to missing cart context
components/cart/cart-context.tsx:CartProvider
Products tagged with 'nextjs-frontend-hidden' in Shopify should be excluded from catalog display, and this tag name won't conflict with merchant's existing tags
If this fails: If merchants use this tag for other purposes or products get tagged accidentally, items disappear from the storefront unexpectedly
lib/constants.ts:HIDDEN_PRODUCT_TAG
Search queries are short enough to fit in URL parameters and don't contain characters that break Next.js routing
If this fails: If users search for very long strings or special characters, the navigation to /search may fail or produce invalid URLs
components/layout/navbar/search.tsx:Form
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Stores Shopify API responses with cache tags for selective invalidation when products or cart data changes
Persists cart ID in browser cookies to maintain cart state across sessions and page loads
Client-side cart state that immediately reflects user actions before server confirmation
Feedback Loops
- Optimistic cart updates (self-correction, balancing) — Trigger: User adds/removes cart items. Action: useOptimistic immediately updates UI while server action syncs with Shopify. Exit: Server action completes and revalidates cache.
- Search refinement (recursive, reinforcing) — Trigger: User applies filters or changes search terms. Action: URL parameters update, triggering new product fetch with refined criteria. Exit: User stops filtering or navigates away.
Delays
- GraphQL API calls (async-processing, ~200-500ms) — Loading states shown while product data fetches from Shopify
- Cart operations (async-processing, ~300-800ms) — Optimistic updates provide immediate feedback while server actions process
- Cache revalidation (eventual-consistency, ~immediate) — Updated data propagates to all pages using the same cache tags
Control Points
- SHOPIFY_STORE_DOMAIN (env-var) — Controls: Which Shopify store to connect to for product and cart data
- SITE_NAME (env-var) — Controls: Brand name displayed in navigation and meta tags
- HIDDEN_PRODUCT_TAG (feature-flag) — Controls: Which products to exclude from public catalog display. Default: nextjs-frontend-hidden
Technology Stack
Provides App Router, React Server Components, caching, and server actions for the e-commerce application framework
Handles component rendering, state management with useOptimistic for cart interactions, and client-server boundaries
Backend service providing GraphQL endpoints for product catalog, cart operations, and checkout functionality
Type safety across Shopify API responses, component props, and cart state management
Utility-first styling for responsive product grids, cart modals, and mobile-optimized layouts
Typography system for consistent brand presentation across the storefront
Key Components
- CartProvider (orchestrator) — Manages cart state across the app using React Context with useOptimistic for instant UI updates while server actions sync with Shopify
components/cart/cart-context.tsx - shopifyFetch (gateway) — GraphQL client that handles all communication with Shopify Storefront API including authentication, caching, and error handling
lib/shopify/index.ts - Navbar (orchestrator) — Server component that fetches menu data and coordinates search, cart modal, and mobile menu presentation
components/layout/navbar/index.tsx - addItem (processor) — Server action that adds products to cart by calling Shopify's addToCart mutation and invalidating cache tags
components/cart/actions.ts - Search (adapter) — Form component that captures search input and redirects to search results page with query parameters
components/layout/navbar/search.tsx - FilterList (processor) — Renders filtering options for products including sort options and category paths with active state management
components/layout/search/filter/index.tsx - GridTileImage (transformer) — Displays product images with labels, hover effects, and responsive sizing in grid layouts
components/grid/tile.tsx
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaCompare commerce
Related Fullstack Repositories
Frequently Asked Questions
What is commerce used for?
Renders product catalogs, shopping carts and checkouts for e-commerce stores vercel/commerce is a 7-component fullstack written in TypeScript. Data flows through 5 distinct pipeline stages. The codebase contains 66 files.
How is commerce architected?
commerce is organized into 3 architecture layers: UI Components, Shopify Integration, App Router. Data flows through 5 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through commerce?
Data moves through 5 stages: Load initial page data → Render product catalog → Handle cart interactions → Process search and filtering → Sync cart state. Product data flows from Shopify's GraphQL API through the shopifyFetch client into React Server Components that render product grids and details. When users interact with the cart, client components trigger server actions that update Shopify while useOptimistic immediately updates the UI. Search queries navigate to results pages where URL parameters drive product fetching and filtering. This pipeline design reflects a complex multi-stage processing system.
What technologies does commerce use?
The core stack includes Next.js 15 (Provides App Router, React Server Components, caching, and server actions for the e-commerce application framework), React 19 (Handles component rendering, state management with useOptimistic for cart interactions, and client-server boundaries), Shopify Storefront API (Backend service providing GraphQL endpoints for product catalog, cart operations, and checkout functionality), TypeScript (Type safety across Shopify API responses, component props, and cart state management), Tailwind CSS (Utility-first styling for responsive product grids, cart modals, and mobile-optimized layouts), Geist Font (Typography system for consistent brand presentation across the storefront). A focused set of dependencies that keeps the build manageable.
What system dynamics does commerce have?
commerce exhibits 3 data pools (Next.js Cache, Cart Cookie), 2 feedback loops, 3 control points, 3 delays. The feedback loops handle self-correction and recursive. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does commerce use?
4 design patterns detected: Server Component + Client Interactivity, Optimistic Updates, GraphQL Fragment Composition, Cache Tag Invalidation.
How does commerce compare to alternatives?
CodeSea has side-by-side architecture comparisons of commerce with medusa. These comparisons show tech stack differences, pipeline design, system behavior, and code patterns. See the comparison pages above for detailed analysis.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.