Skip to main content
The Openfront storefront provides a modern, high-performance shopping experience for your customers. Built with Next.js 15 and the App Router, it delivers fast page loads, seamless navigation, and an intuitive checkout flow.

Architecture

The storefront is organized as a feature-complete Next.js application:
app/(storefront)/[countryCode]/
├── (main)/              # Main shopping experience
│   ├── products/        # Product detail pages
│   ├── collections/     # Collection browsing
│   ├── categories/      # Category browsing
│   ├── cart/           # Shopping cart
│   ├── account/        # Customer account dashboard
│   └── order/          # Order tracking
└── (checkout)/         # Isolated checkout flow
    └── checkout/       # Multi-step checkout

Key Features

Multi-Regional Support

All storefront routes are prefixed with [countryCode] to provide:
  • Region-specific pricing and currency
  • Localized product availability
  • Country-specific shipping options
  • Tax calculations based on location

Server Components

The storefront leverages React Server Components for:
  • Fast initial page loads - HTML rendered on the server
  • SEO optimization - Fully rendered content for search engines
  • Reduced JavaScript - Only interactive components ship to the client
  • Data fetching - Direct GraphQL queries without API roundtrips

Responsive Design

Built mobile-first with:
  • Touch-optimized product galleries
  • Mobile-specific navigation patterns
  • Adaptive layouts for all screen sizes
  • Performance-optimized images

Core Modules

The storefront is organized into feature modules under features/storefront/modules/:

Products

Product detail pages with image galleries, variant selection, and related products

Cart

Persistent shopping cart with quantity management and guest checkout support

Checkout

Multi-step checkout with address validation, shipping selection, and payment

Account

Customer dashboard for orders, addresses, profile, and invoicing

Customer Journey

The typical customer flow through the storefront:

Data Layer

The storefront communicates with the Openfront backend via GraphQL:
// features/storefront/lib/data/
export async function getProductByHandle({ handle, regionId }) {
  const GET_PRODUCT_QUERY = gql`
    query GetProductByHandle($handle: String!, $regionId: ID!) {
      product(where: { handle: $handle }) {
        id
        title
        description
        productVariants {
          id
          prices(where: { region: { id: { equals: $regionId } } }) {
            amount
            currency { code }
          }
        }
      }
    }
  `
  return openfrontClient.request(GET_PRODUCT_QUERY, { handle, regionId })
}

Performance

Image Optimization

Product images are optimized using Next.js Image component:
  • Automatic format selection (WebP, AVIF)
  • Responsive sizes for different viewports
  • Lazy loading below the fold

Caching Strategy

The storefront uses React’s cache() function for:
  • Deduplicating data fetches during rendering
  • Consistent data across Server Components
  • Reduced database queries

Revalidation

Data is revalidated using Next.js tags:
revalidateTag('cart')      // After cart updates
revalidateTag('products')  // After product changes
revalidateTag('customer')  // After profile updates

Homepage

Featured collections and products with customizable hero section:
// features/storefront/screens/HomePage.tsx
export async function HomePage({ params }) {
  const region = await getRegion(countryCode)
  const collections = await getCollectionsListByRegion(0, 3, region.id)
  
  return (
    <>
      <Hero title={store.homepageTitle} />
      <FeaturedProducts collections={collections} />
    </>
  )
}

Product Browsing

Customers can browse products by:
  • Collections - Curated product groupings
  • Categories - Hierarchical product organization
  • Search - Full-text product search (when configured)

Templates

Each module provides templates for common layouts:
// features/storefront/modules/products/templates/
const ProductTemplate = ({ product, region }) => (
  <div className="grid lg:grid-cols-3">
    <ProductInfo product={product} />      {/* Left: Details */}
    <ImageGallery images={product.images} /> {/* Center: Gallery */}
    <ProductActions product={product} />   {/* Right: Add to cart */}
  </div>
)

Next Steps

Product Catalog

Learn how products are displayed and variants are managed

Shopping Cart

Understand cart management and persistence

Checkout

Explore the multi-step checkout process

Customer Accounts

See how customers manage orders and profiles

Build docs developers (and LLMs) love