# saleor/storefront: A Saleor Storefront Template with Server-First Checkout

> saleor/storefront is a TypeScript storefront template for Saleor, built with React, Next.js App Router, GraphQL and Tailwind CSS. It suits teams needing international routing and checkout workflows, but its custom LICENSE and new checkout release require review.

**saleor/storefront** — Saleor Storefront built using React, Next.js with App Router, TypeScript, GraphQL, and Tailwind CSS.

- Repository: https://github.com/saleor/storefront
- Website: https://storefront.saleor.io
- Stars: 1,636 · Forks: 898
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/saleor-storefront

## What saleor/storefront replaces for Saleor teams

saleor/storefront, presented in the README as Paper, is a storefront template for Saleor rather than a general-purpose ecommerce application. It targets teams that already operate Saleor or plan to do so and need a customer-facing React application for browsing products, navigating categories, viewing product details, managing carts and completing checkout.

The project is a Next.js application using the App Router, TypeScript, GraphQL and Tailwind CSS. Its catalog and checkout requests depend on Saleor's GraphQL API, so adoption also means adopting Saleor concepts such as channels, product variants, localized content and checkout mutations. The repository contains a Dockerfile, pnpm workspace files, an environment example, GraphQL code-generation configuration and Playwright and Vitest files. It is an application repository, not a small theme package.

The template is aimed at engineers who want a starting point they can change. The README calls it a minimal, production-ready storefront template, while also warning that it is a new release with some rough edges. That distinction matters. The repository provides application structure and documented conventions, but adapting product presentation, commerce rules, content, analytics, deployment and operations remains the adopting team's work.

## Catalog, routing and GraphQL data flow

The documented browsing model combines Next.js server-rendered surfaces with Saleor data. Product pages use Partial Prerendering. Product names, attributes and SEO data remain in a static cached shell, while the variant gallery and add-to-cart area stream through Suspense when `searchParams` change. This is a concrete split between shell data and interactive catalog data, rather than a claim that the entire page is static.

International routing is part of the URL contract. Browse paths use `/{locale}/{channel}/...`, with examples such as `/en/us/products/hoodie` and `/pl/pl/products/bluza`. The locale and channel determine the market context. Saleor supplies translated catalog copy, channel pricing and currency, while storefront interface messages live in `messages/{locale}.json`. The README distinguishes three string systems: Saleor catalog translations, merchant-editable storefront content and code-owned interface strings handled with `next-intl`. This separation gives each translation a clear location, but it also means changes may involve more than one file or system.

Saleor may contain channels that a storefront should not expose. Paper exposes only slugs configured through `STOREFRONT_CHANNELS`; disallowed channel URLs return 404. For a single-channel store, `NEXT_PUBLIC_DEFAULT_CHANNEL` supplies the fallback and the footer selector is hidden automatically. Product and category slugs can be translated per language when handles are configured in Saleor. The application resolves and redirects those slugs and emits corresponding canonical and hreflang metadata.

The repository includes `.graphqlrc.ts` and package scripts that invoke `graphql-codegen`. Generated operations therefore add a maintenance boundary: a Saleor schema change can require regenerated artifacts, source changes and review. Teams should treat GraphQL generation as part of upgrading the application, not as disposable build output.

## How server-first checkout handles cart state

The checkout design is the repository's most distinctive feature. The README maps the storefront cart in `src/lib/checkout.ts` to the checkout surface under `src/app/(checkout)/checkout/`. `CheckoutSessionLoader` loads checkout and `me` on entry as an RSC, while `CheckoutDataProvider` is described as a client-side cache of server truth. This replaces the old urql-based browser checkout architecture described in the checkout migration documentation.

Checkout progression is URL-driven through `?step=contact|shipping|payment`. Changing a step performs a shallow update instead of a full page refetch, and browser Back navigation walks through the checkout sequence. After payment, the documented confirmation route is `/order/{hmac}`. An email-based `/order/{saleorId}` route is redacted until Saleor recognizes the requester. The README also states that the legacy `/checkout/complete?order=` path redirects.

Payments are organized through an `INTEGRATED_GATEWAYS` registry, with Stripe and Dummy listed in the README. Project documentation points to a `checkout-payment-gateways` skill for adding gateways. That is an explicit extension boundary, but the README does not provide a complete production setup for every provider.

The shared backend-for-frontend authentication route is `/api/auth/login`, with `resolveSessionUser` handling guest, authenticated and unavailable states. Checkout consequently depends on session resolution, Saleor mutations, order visibility and the selected gateway. Teams adding a gateway or changing authentication should inspect those connections first. The README describes the architecture, but it does not enumerate every failure condition for expired sessions, declined payments, unavailable Saleor instances or duplicate order submission.

## Installing Paper and starting a local Saleor connection

The README points to Saleor documentation for headless storefront concepts, while `.env.example` identifies the application settings needed to connect the frontend to Saleor. The Dockerfile uses pnpm with Node 24 Alpine. The following command appears in the Dockerfile and installs the checked-in dependency graph:

```bash
pnpm i --frozen-lockfile --prefer-offline
```

The repository provides `.env.example`, which documents the required Saleor API URL and the storefront URL. Set `NEXT_PUBLIC_SALEOR_API_URL` to the GraphQL endpoint of the Saleor instance. The example retains a trailing slash. Also set `NEXT_PUBLIC_STOREFRONT_URL` and `NEXT_PUBLIC_DEFAULT_CHANNEL`. For a multi-channel store, configure `STOREFRONT_CHANNELS`; for additional locales, configure the locale variables documented in `.env.example`.

The package scripts generate both storefront and checkout GraphQL operations before development. The `generate:all` script is part of the `predev`, `prebuild` and `pretypecheck` hooks. The Dockerfile uses the following command for its production build:

```bash
pnpm build
```

The `docker-compose.yml` file exposes the `saleor-storefront` service on port 3000, but the file does not define a Saleor backend. The API endpoint and other frontend environment settings still need to be supplied. The README does not document a seed-data command or a universal test account.

## Verification, deployment and upgrade cost for Paper

The repository contains several verification paths. The package scripts include type checking, ESLint, design-token checks, deprecated product-variant checks, data-layer lock checks, core lock checks and Vitest tests. The `verify` script combines documentation checks, design-token checks, GraphQL variant checks, lock checks, type checking, linting and unit tests.

There are separate Playwright commands for end-to-end tests, including `test:e2e:instant` and `test:e2e:checkout`. These scripts give an adopting team defined entry points for development verification, although the README does not present a complete release procedure or supported upgrade matrix.

The upgrade surface extends beyond application dependencies. GraphQL operations are generated against Saleor schemas, so a schema change can require regeneration and code review. Locale definitions in `src/config/locale.ts`, the payment registry, route structure, design tokens and lock files all require deliberate maintenance. The repository includes a migration directory for forks using the old urql checkout, confirming that some checkout upgrades involve source changes rather than dependency updates alone.

Deployment also requires environment discipline. The repository examples include `NEXT_PUBLIC_SALEOR_API_URL`, `NEXT_PUBLIC_STOREFRONT_URL`, `NEXT_PUBLIC_DEFAULT_CHANNEL`, `STOREFRONT_CHANNELS`, locale settings, `NEXT_PUBLIC_CHECKOUT_URL`, `NEXT_PUBLIC_ENABLE_STRIPE_PAYMENTS` and `SALEOR_APP_TOKEN`. The Vercel deployment description explains that the channel slug comes from Saleor Dashboard under `Configuration > Channels`. Incorrect public URL or redirect-origin settings can affect canonical URLs, metadata and checkout navigation.

The repository is not archived, and its last push was on 2026-10-14. That date records recent repository activity, but it does not replace examining the commit history and custom license for the exact version being adopted. The package is private and declares `SEE LICENSE IN LICENSE`. The README does not summarize the license rights or restrictions, so the `LICENSE` file is the controlling source for any reuse assessment. This review is not legal advice.

## When Paper is the wrong storefront foundation

Paper is a poor fit for a team seeking a portable theme. Its GraphQL operations, channel model, checkout session loader, order confirmation HMAC routes and `me` resolution reflect Saleor's API and session design. A team using another commerce backend would need to replace too much of the catalog and checkout layer for the template to retain its main value.

It is also a poor fit when the team wants checkout without application ownership. The README describes the release as new and warns about rough edges. Payment gateways are registry-based, and the listed integrations are Stripe and Dummy. The README does not claim complete coverage of every Saleor tax rule, address format, payment error, session state or order visibility condition.

A conventional hosted ecommerce platform can be a better choice when a team wants the provider to manage its catalog, checkout, taxes and administration with minimal application engineering. The architectural difference is concrete. A hosted platform delegates the commerce backend and much of checkout operation to its vendor. Paper gives teams a customizable Next.js front end connected to Saleor, leaving them responsible for that integration and its deployment.

Paper is also the wrong choice when the team cannot operate a TypeScript and GraphQL application. Its verification, generation, checkout and deployment configuration require engineering ownership. That is a meaningful cost when the goal is primarily to select and configure an off-the-shelf channel theme.

## Adoption decision for saleor/storefront

Engineers already committed to Saleor gain the most from this template because its routing, catalog queries, channels and checkout are designed around that backend. The server-first checkout also offers a coherent alternative to browser-side urql checkout, while the channel and locale restrictions provide explicit controls over which Saleor markets the front end exposes.

The adoption boundary is equally clear. Paper is a new template with a custom license, generated GraphQL code and substantial commerce integration behavior. Teams should not adopt it as a generic React theme or assume that a successful build establishes checkout readiness. The first checks should be the `LICENSE` file, Saleor channel and locale configuration, session resolution, payment registry and production environment variables. If those pass review, saleor/storefront is specifically suited to a Saleor-backed team willing to own the front end and its upgrade path.

## Conclusion

Adopt saleor/storefront when your team is building for Saleor and can own the template, GraphQL schema changes, deployment configuration and checkout operations. Do not treat it as a license-neutral, drop-in theme for another commerce platform. Verify the custom LICENSE first, then check channel and locale configuration, checkout session behavior, payment registration and deployment variables before committing production traffic.

## FAQ

### How do I install saleor/storefront locally?

Install dependencies with `pnpm i --frozen-lockfile --prefer-offline`, then use the settings in `.env.example` to configure the Saleor API endpoint, storefront URL and channel. The repository also provides `pnpm build` as its production build command.

### What Saleor configuration does saleor/storefront require?

`.env.example` identifies `NEXT_PUBLIC_SALEOR_API_URL` as the Saleor GraphQL endpoint. The frontend also uses `NEXT_PUBLIC_DEFAULT_CHANNEL`, while a multi-channel store can configure `STOREFRONT_CHANNELS` with the allowed channel slugs.

### Does saleor/storefront support international storefronts?

Yes. Its documented browse URLs use `/{locale}/{channel}/...`, with locale-specific catalog data, translated handles, channel pricing, currency, canonical metadata and hreflang. Interface messages are stored under `messages/{locale}.json`, and additional locales can be defined in `src/config/locale.ts`.

## Sources

- [Issues](https://github.com/saleor/storefront/issues)
- [Project website](https://storefront.saleor.io)
- [README](https://github.com/saleor/storefront/blob/main/README.md)
- [saleor/storefront on GitHub](https://github.com/saleor/storefront)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/saleor-storefront
