Project Structure

Learn about the Storefront Next project structure to navigate code quickly and follow conventions that keep your codebase maintainable as it grows.

Overview

A Storefront Next project is built on React Router 7 in framework mode, and uses Vite as the build tool. The structure separates your app code (src/) from configuration files at the project root.

my-storefront/
├── src/                        # Application code
│   ├── routes/                 # Page components (file-based routing)
│   ├── components/             # Reusable UI components
│   ├── lib/                    # Utilities and API clients
│   ├── hooks/                  # Custom React hooks
│   ├── providers/              # React context providers
│   ├── middlewares/            # Request/response middleware
│   ├── locales/                # Translation files
│   ├── root.tsx                # Application shell and layout
│   ├── routes.ts               # Route configuration
│   └── app.css                 # Global styles (Tailwind)
├── public/                     # Static assets (images, fonts)
├── types/                      # TypeScript type definitions
├── config.server.ts            # Commerce API and site configuration
├── vite.config.ts              # Build configuration
├── react-router.config.ts      # React Router settings
└── package.json                # Dependencies and scripts

Application Code in src/

Routes

The routes/ directory contains your page components. Storefront Next uses React Router's file-based routing, where file names determine URL paths.

src/routes/
├── _index.tsx                  # Home page (/)
├── category.$.tsx              # Category pages (/category/*)
├── product.$productId.tsx      # Product pages (/product/:productId)
├── cart.tsx                    # Cart page (/cart)
├── checkout.tsx                # Checkout (/checkout)
├── account.tsx                 # Account layout
├── account._index.tsx          # Account home (/account)
├── account.orders.tsx          # Order history (/account/orders)
└── action.cart-item-add.tsx    # Server action for adding to cart

File Naming Conventions

Pattern Example URL Purpose
_index.tsx _index.tsx / Index route (renders at parent path)
name.tsx cart.tsx /cart Static route
$param product.$productId.tsx /product/:productId Dynamic segment that captures a value
$.tsx category.$.tsx /category/* Splat/catch-all route
parent.child.tsx account.orders.tsx /account/orders Nested route
action.* action.cart-item-add.tsx — Server action (not a navigable page)

note: Files starting with underscore (_) have special meaning. _index.tsx renders at the parent path, while a _layout.tsx file creates a layout wrapper without adding a URL segment.

The routes.ts file configures routing behavior. The flatRoutes() function scans your src/routes/ directory and generates route configuration automatically based on file names. You rarely have to modify this file.

// src/routes.ts
import { type RouteConfig } from '@react-router/dev/routes';
import { flatRoutes } from '@react-router/fs-routes';

export default flatRoutes() satisfies RouteConfig;
<!-- For more details on routing patterns, see [Routing](sfnext-routing.md). -->

Components

The components/ directory contains reusable UI elements organized by feature area.

src/components/
├── ui/                         # Base UI primitives (buttons, inputs, dialogs)
├── header/                     # Site header and navigation
├── footer/                     # Site footer
├── product-view/               # Product display components
├── product-tile/               # Product cards for listings
├── cart/                       # Cart components
└── ...

The ui/ subdirectory contains shadcn/ui components—accessible, customizable primitives that you can modify directly.

Create a component when:

  • The UI element is used in multiple places.
  • The component encapsulates complex logic or state.
  • You want to test the UI in isolation (via Storybook).
<!-- For more on the component library, see [Components](sfnext-components.md). -->

Lib

The lib/ directory contains utilities, API clients, and business logic that isn't tied to React.

src/lib/
├── api/                        # Commerce API client functions
├── utils/                      # General utilities (formatting, validation)
└── ...

Place code here when it:

  • Doesn't use React hooks or components.
  • Could be shared across multiple routes or components.
  • Handles data transformation or business logic.

Hooks

Custom React hooks extract reusable stateful logic from components.

src/hooks/
├── use-product.ts              # Product data access
├── use-cart.ts                 # Cart operations
├── use-navigation.ts           # Navigation utilities
└── ...

When to create a custom hook:

  • Multiple components need the same stateful logic.
  • You want to encapsulate complex operations (like API calls with loading states).
  • You must share behavior across routes.

Providers

React context providers supply data and functionality throughout the app.

src/providers/
├── cart-provider.tsx           # Cart state and operations
├── locale-provider.tsx         # Internationalization context
└── ...

Providers wrap the app in root.tsx and make data available to any nested component without prop drilling.

Middlewares

Request and response middleware that runs before route loaders:

src/middlewares/
├── auth-middleware.server.ts   # Authentication (server-side)
├── auth-middleware.client.ts   # Authentication (client-side)
├── i18n-middleware.ts          # Locale detection and setup
└── ...

Middleware is registered in root.tsx and executes in order for each request. Use middleware to:

  • Parse authentication tokens
  • Detect user locale
  • Set up shared context that loaders need

For details on implementing middleware, see Storage and Sessions.

Locales

Translation files for internationalization:

src/locales/
├── en-US.json
├── fr-FR.json
└── ...

See Internationalization for setup and usage.

Root File (root.tsx)

The root.tsx file is your app's entry point. It exports several key pieces that define your app's behavior:

Export Purpose
middleware Server middleware chain (auth, locale detection)
clientMiddleware Client middleware chain (runs during client navigation)
loader Root data loader (fetches data needed by all pages)
Layout HTML document structure (<html>, <head>, <body>)
default (App) Application shell with header, footer, and <Outlet /> for page content

Most customization happens in middleware and the App component. Typically, you only need to modify Layout when changing document-level meta tags or adding scripts.

Configuration Files

File Purpose
config.server.ts Commerce API connection and storefront settings. See Configuration.
vite.config.ts Build plugins, path aliases, Server-Side Rendering (SSR) settings. See Build Tools.
react-router.config.ts React Router framework options
tsconfig.json TypeScript compiler options
package.json Dependencies and npm scripts

Where to Put Code Elements

You want to... Put it in...
Add a new page src/routes/ (file name = URL path)
Create a reusable component src/components/
Add a server action src/routes/action.*.tsx
Add a utility function src/lib/
Create a custom hook src/hooks/
Add translations src/locales/
Add static assets (images) public/
Add global styles src/app.css
Configure commerce or storefront settings config.server.ts

Example: Adding a Wishlist Feature

Here's how the project structure guides you when adding a new feature:

src/
├── routes/
│   ├── wishlist.tsx              # 1. Page at /wishlist
│   └── action.wishlist-add.tsx   # 2. Server action for adding items
├── components/
│   └── wishlist/
│       ├── wishlist-item.tsx     # 3. UI components
│       └── wishlist-empty.tsx
├── hooks/
│   └── use-wishlist.ts           # 4. Hook for wishlist operations
└── lib/
    └── api/
        └── wishlist.ts           # 5. API client functions

This separation keeps your code organized.

  • Routes define what URLs exist and load data.
  • Components handle presentation.
  • Hooks manage stateful logic.
  • Lib contains pure functions and API calls.

Customizing Entry Files

React Router provides default entry files for client hydration and server rendering. These entry files are hidden by default but can be revealed for advanced customization.

npx react-router reveal

This command creates entry.client.tsx and entry.server.tsx in your src/ directory.

When to customize:

  • Initialize client libraries before hydration
  • Add custom error reporting (for example, Sentry)
  • Modify server response headers
  • Customize streaming behavior

For most projects, the default entry files work without modification.

See Also