> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> Server-first architecture, project structure, and auth flow

## Server-First Pattern

The storefront follows a **server-first architecture** where all API calls are made server-side. The Spree API key is never exposed to the browser.

```
Browser → Server Action → @spree/sdk → Spree API
         (with httpOnly cookies via src/lib/spree helpers)
```

* **Server Actions** (`src/lib/data/`) — call `@spree/sdk` directly with auth/cookie helpers from `src/lib/spree`
* **httpOnly Cookies** — auth tokens, cart tokens, and locale are stored securely
* **No Client-Side API Calls** — the Spree API key stays on the server
* **Auto-Localization** — locale and country are read from cookies via `getLocaleOptions()`

## Project Structure

```
src/
├── app/
│   └── [country]/[locale]/          # Localized routes
│       ├── (storefront)/            # Main storefront layout
│       │   ├── page.tsx             # Homepage
│       │   ├── account/             # Customer account
│       │   │   ├── addresses/       # Address management
│       │   │   ├── credit-cards/    # Saved payment methods
│       │   │   ├── gift-cards/      # Gift cards
│       │   │   ├── orders/          # Order history
│       │   │   │   └── [id]/        # Order details
│       │   │   ├── profile/         # Profile settings
│       │   │   └── register/        # Registration
│       │   ├── cart/                # Shopping cart
│       │   ├── products/            # Product listing
│       │   │   └── [slug]/          # Product details
│       │   ├── t/[...permalink]/    # Category pages
│       │   └── categories/          # Category overview
│       └── (checkout)/              # Checkout layout (no header/footer)
│           ├── checkout/[id]/       # Checkout flow
│           └── order-placed/[id]/   # Order confirmation
├── components/
│   ├── cart/                        # CartDrawer
│   ├── checkout/                    # AddressStep, DeliveryStep, PaymentStep, etc.
│   ├── layout/                      # Header, Footer, CountrySwitcher
│   ├── navigation/                  # Breadcrumbs
│   ├── products/                    # ProductCard, ProductGrid, Filters, MediaGallery, VariantPicker
│   └── search/                      # SearchBar
├── contexts/
│   ├── AuthContext.tsx              # Auth state
│   ├── CartContext.tsx              # Client-side cart state sync
│   ├── CheckoutContext.tsx          # Checkout flow state
│   └── StoreContext.tsx             # Store/locale/currency state
├── hooks/
│   ├── useCarouselProducts.ts      # Product carousel data
│   └── useProductListing.ts        # Product listing with filters
└── lib/
    ├── analytics/                   # GTM integration
    ├── constants.ts                 # App constants
    ├── data/                        # Server Actions (call @spree/sdk directly)
    │   ├── addresses.ts             # Address CRUD
    │   ├── cart.ts                  # Cart operations
    │   ├── checkout.ts              # Checkout flow
    │   ├── cookies.ts               # Auth check helper
    │   ├── countries.ts             # Countries/regions
    │   ├── credit-cards.ts          # Payment methods
    │   ├── customer.ts              # Auth & profile
    │   ├── gift-cards.ts            # Gift cards
    │   ├── orders.ts                # Order history
    │   ├── payment.ts               # Payment processing
    │   ├── products.ts              # Product queries
    │   ├── categories.ts            # Categories
    │   └── utils.ts                 # Shared helpers (actionResult, withFallback)
    └── utils/                       # Client utilities
        ├── address.ts               # Address formatting
        ├── cookies.ts               # Cookie helpers
        ├── credit-card.ts           # Card formatting
        ├── path.ts                  # URL path helpers
        └── product-query.ts         # Product filter query builder
```

## Authentication Flow

1. User submits login form
2. Server action calls `@spree/sdk` to authenticate
3. JWT token is stored in an httpOnly cookie via `src/lib/spree` cookie helpers
4. Subsequent requests use `withAuthRefresh()` which reads the token from cookies automatically
5. Token is never accessible to client-side JavaScript

```typescript theme={"theme":"night-owl"}
// src/lib/data/customer.ts
import { getClient, withAuthRefresh, setAccessToken, setRefreshToken } from '@/lib/spree'

export async function login(email: string, password: string) {
  const result = await getClient().auth.login({ email, password })
  await setAccessToken(result.token)
  await setRefreshToken(result.refresh_token)
  return { success: true, user: result.user }
}

export async function getCustomer() {
  return withAuthRefresh(async (options) => {
    return getClient().customer.get(options) // reads token from cookie
  })
}
```

## Multi-Region Support

The storefront supports multiple countries and currencies via URL segments:

```
/us/en/products          # US store, English
/de/de/products          # German store, German
/uk/en/products          # UK store, English
```

A middleware (`src/proxy.ts`) uses `createSpreeMiddleware` from `src/lib/spree` to detect the visitor's country and locale, then redirects to the correct URL prefix. The `CountrySwitcher` component lets users change regions manually.

## Server Actions

All data fetching is done through server actions in `src/lib/data/`. These call `@spree/sdk` directly, using `src/lib/spree` helpers for auth and locale:

```typescript theme={"theme":"night-owl"}
// Products — use getLocaleOptions() for locale-aware reads
import { getProducts, getProduct, getProductFilters } from '@/lib/data/products'

const products = await getProducts({ limit: 12 })
const product = await getProduct('product-slug')
const filters = await getProductFilters()

// Cart — use getCartOptions()/requireCartId() for cart operations
import { getCart, addToCart, updateCartItem, removeCartItem } from '@/lib/data/cart'

const cart = await getCart()
await addToCart('var_xxx', 1)
await updateCartItem('li_xxx', 2)
await removeCartItem('li_xxx')

// Authentication — use withAuthRefresh() for authenticated endpoints
import { login, register, logout, getCustomer } from '@/lib/data/customer'

await login('user@example.com', 'password')
const customer = await getCustomer()
await logout()

// Addresses — use withAuthRefresh() for customer data
import { getAddresses, createAddress, updateAddress, deleteAddress } from '@/lib/data/addresses'

const addresses = await getAddresses()
await createAddress({ first_name: 'John', ... })
```
