1---2name: nextjs-react3description: Build Next.js and React applications for Saleor — App Router, server and client components, GraphQL client integration, MacawUI in Apps, and Tailwind CSS. Use when building Saleor storefronts or Apps with Next.js.4---56# Next.js & React for Saleor78## Before writing code910**Fetch live docs**:111. Web-search `site:nextjs.org docs app` for current Next.js App Router documentation122. Web-search `site:docs.saleor.io storefront` for Saleor storefront development guide133. Web-search `site:github.com saleor storefront` for the official Saleor storefront template source144. Web-search `site:github.com saleor macaw-ui` for MacawUI component library reference155. Web-search `saleor app template Next.js saleor-app-sdk` for App development patterns166. Fetch `https://docs.saleor.io/docs/developer/app-store/apps/overview` for App architecture1718## Next.js App Router Conventions1920### File Conventions2122| File | Purpose | Rendering |23|------|---------|-----------|24| `layout.tsx` | Shared layout wrapping child routes | Server component (default) |25| `page.tsx` | Unique UI for a route segment | Server component (default) |26| `loading.tsx` | Loading UI (React Suspense) | Server component |27| `error.tsx` | Error boundary for route segment | Client component (required) |28| `not-found.tsx` | 404 UI for route segment | Server component |29| `template.tsx` | Re-rendered layout (no state persistence) | Server component |30| `route.ts` | API route handler | Server-only |3132### Routing Patterns for Saleor Storefronts3334| Route | Segment | Purpose |35|-------|---------|---------|36| `/[channel]` | Dynamic channel | Multi-channel routing |37| `/[channel]/products` | Product listing | Category/collection pages |38| `/[channel]/products/[slug]` | Product detail | Single product page |39| `/[channel]/cart` | Cart | Shopping cart |40| `/[channel]/checkout` | Checkout | Checkout flow |41| `/[channel]/account` | Account | Customer dashboard |42| `/[channel]/search` | Search | Product search results |4344- Use dynamic segments `[channel]` for multi-channel support45- Use route groups `(storefront)` and `(dashboard)` to organize layouts4647## Server vs Client Components4849### Decision Matrix5051| Criterion | Server Component | Client Component |52|-----------|-----------------|-----------------|53| **Data fetching** | Fetch directly (no waterfall) | Use `useQuery` hooks |54| **SEO critical** | Yes (HTML in response) | No (client-rendered) |55| **Interactivity** | None (static output) | Click, input, state |56| **Hooks** | Cannot use hooks | `useState`, `useEffect`, etc. |57| **Bundle size** | Zero JS sent to client | Included in JS bundle |5859### Component Patterns for Saleor6061| Component | Type | Reason |62|-----------|------|--------|63| **Product list page** | Server | SEO, data fetching |64| **Product detail page** | Server | SEO, data fetching |65| **Add to cart button** | Client | Interactivity, state |66| **Cart sidebar** | Client | State management, animation |67| **Checkout form** | Client | Form state, validation |68| **Search bar** | Client | Input handling, debounce |69| **Navigation** | Server | Static, SEO links |70| **Price display** | Server | Channel-aware, static |7172- Default to server components — add `"use client"` only when needed; pass server-fetched data as props to client components7374## GraphQL Client Integration7576### urql (Saleor Recommended)7778| Package | Purpose |79|---------|---------|80| `@urql/core` | Core urql client |81| `@urql/next` | Next.js App Router integration |82| `graphql` | GraphQL parsing (peer dependency) |8384### Setup Pattern8586| Concern | Implementation |87|---------|---------------|88| **Server client** | Create urql client in server utility, use in server components |89| **Client provider** | Wrap client components with `UrqlProvider` in layout |90| **Auth header** | Add `Authorization: Bearer <token>` via `fetchOptions` |91| **Channel header** | Add `saleor-channel: <slug>` via `fetchOptions` |92| **SSR** | Use `@urql/next` for SSR data hydration |9394### Apollo Client Alternative9596- Use `@apollo/client` with `@apollo/experimental-nextjs-app-support`97- Provides normalized caching (useful for complex state)98- Heavier bundle than urql99100## Data Fetching Patterns101102| Pattern | Where | How |103|---------|-------|-----|104| **Server component fetch** | `page.tsx`, `layout.tsx` | `await client.query()` directly |105| **Client query hook** | `"use client"` components | `useQuery(Document, { variables })` |106| **Server action** | Form submissions | `"use server"` functions calling GraphQL |107| **Route handler** | `route.ts` | API endpoint calling Saleor GraphQL |108| **Parallel fetching** | Server component | `Promise.all([query1, query2])` |109110- Fetch data as high in the component tree as possible111- Use `Promise.all` for parallel independent queries112- Use server actions for mutations (checkout updates, cart modifications)113114## Caching Strategies115116| Strategy | Scope | Configuration |117|----------|-------|---------------|118| **Static** | Build time | `export const revalidate = false` |119| **ISR** | Time-based revalidation | `export const revalidate = 60` (seconds) |120| **On-demand** | Webhook-triggered | `revalidatePath()` or `revalidateTag()` |121| **No cache** | Always fresh | `export const dynamic = "force-dynamic"` |122123### Saleor Caching Recommendations124125| Page | Strategy | Rationale |126|------|----------|-----------|127| **Product listing** | ISR (60s) | Content changes infrequently |128| **Product detail** | ISR (60s) + on-demand | Revalidate on product webhook |129| **Cart / Checkout** | No cache | User-specific, transactional |130| **Static pages** | Static | CMS content, rarely changes |131132## Environment Variables133134| Variable | Where | Purpose |135|----------|-------|---------|136| `NEXT_PUBLIC_SALEOR_API_URL` | Client + Server | Saleor GraphQL endpoint |137| `SALEOR_API_URL` | Server only | Server-side GraphQL endpoint |138| `NEXT_PUBLIC_DEFAULT_CHANNEL` | Client + Server | Default channel slug |139| `SALEOR_APP_TOKEN` | Server only | App token for authenticated queries |140141- Prefix with `NEXT_PUBLIC_` for client-accessible variables142- Keep secrets (App tokens, API keys) server-only (no prefix)143144## Tailwind CSS Setup145146| Step | Action |147|------|--------|148| **Install** | `npm install -D tailwindcss @tailwindcss/postcss postcss` |149| **Configure** | Add `@tailwindcss/postcss` to `postcss.config.js` |150| **Content paths** | Set `content` in `tailwind.config.ts` to include all component files |151| **Global import** | Add `@import "tailwindcss"` to `globals.css` |152153- The official Saleor storefront template uses Tailwind CSS154- Use CSS custom properties for theme tokens (channel-specific branding)155156## MacawUI Integration for Apps157158MacawUI is the Saleor Dashboard component library used in Saleor Apps:159160| Component Category | Examples |161|-------------------|----------|162| **Layout** | `Box`, `Layout`, `Sidebar` |163| **Forms** | `Input`, `Select`, `Checkbox`, `Multiselect` |164| **Data display** | `List`, `Table`, `Chip`, `Tag` |165| **Feedback** | `Alert`, `Banner`, `Skeleton` |166| **Actions** | `Button`, `IconButton`, `Dropdown` |167168| Context | UI Library | Reason |169|---------|-----------|--------|170| **Saleor App (Dashboard iframe)** | MacawUI | Consistent Dashboard look and feel |171| **Storefront** | Tailwind CSS / custom | Brand-specific design |172173- Install via `npm install @saleor/macaw-ui`174- Wrap App root with `<ThemeProvider>` from MacawUI175- MacawUI follows the Saleor design system (spacing, colors, typography)176177## Image Optimization178179| Feature | Configuration |180|---------|---------------|181| **next/image** | Use for all product and media images |182| **Remote patterns** | Add Saleor media domain to `next.config.js` `images.remotePatterns` |183| **Sizes** | Set `sizes` attribute for responsive images |184| **Priority** | Add `priority` to above-the-fold images (hero, first product) |185| **Formats** | Next.js auto-serves WebP/AVIF when supported |186187## Best Practices188189- Default to server components and add `"use client"` only for interactivity190- Fetch data in server components and pass as props to client components191- Use the App Router file conventions (`page.tsx`, `layout.tsx`, `error.tsx`) consistently192- Set up GraphQL code generation for type-safe queries and mutations193- Use ISR with on-demand revalidation for product pages (webhook-triggered)194- Include `saleor-channel` header in all GraphQL client configurations195- Use MacawUI for Dashboard App UI and Tailwind CSS for storefronts196- Optimize images with `next/image` and configure remote patterns for Saleor media197- Keep environment variables separated between server-only and client-accessible198199Fetch the Next.js and Saleor storefront documentation for current App Router patterns, GraphQL client setup, and component conventions before implementing.