Skip to main content

sfnext-routing

Add and change pages in a Storefront Next project: flat-file routes in src/routes, layout routes (_app, _checkout, _empty), splat routes for product and category pages, action.* and resource.* routes, src/route-paths.ts (routes, resourceRoutes, routeHref), site-aware Link and useNavigate wrappers, SeoMeta and JsonLd head tags, multi-site /:siteId/:localeId URL prefixes, url.seoRoutes and excludeRoutes, extension routes, and the SLAS callback routes. Use for "add a page", "new route", "why is my link missing the site prefix", "route file naming", "redirect to login", or a 404 on a new URL. Do not use for loader/action/fetcher data code (use `storefront-next:sfnext-data-fetching`), shouldRevalidate (use `storefront-next:sfnext-revalidation`), SEO strategy such as sitemaps and canonical rules (use `storefront-next:sfnext-seo`), or Page Designer regions (use `storefront-next:sfnext-page-designer`).

Datos de origen

Repositorio
SalesforceCommerceCloud/b2c-developer-tooling
Última actividad en el origen
4 de octubre de 2026 a las 16:40
Idioma detectado de SKILL.md
inglés
Estrellas
56
Forks
22

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
4 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
sfnext-routing
description
Add and change pages in a Storefront Next project: flat-file routes in src/routes, layout routes (_app, _checkout, _empty), splat routes for product and category pages, action.* and resource.* routes, src/route-paths.ts (routes, resourceRoutes, routeHref), site-aware Link and useNavigate wrappers, SeoMeta and JsonLd head tags, multi-site /:siteId/:localeId URL prefixes, url.seoRoutes and excludeRoutes, extension routes, and the SLAS callback routes. Use for "add a page", "new route", "why is my link missing the site prefix", "route file naming", "redirect to login", or a 404 on a new URL. Do not use for loader/action/fetcher data code (use `storefront-next:sfnext-data-fetching`), shouldRevalidate (use `storefront-next:sfnext-revalidation`), SEO strategy such as sitemaps and canonical rules (use `storefront-next:sfnext-seo`), or Page Designer regions (use `storefront-next:sfnext-page-designer`).
# Storefront Next Routing Storefront Next uses React Router 7 framework mode with file-based routes. Every route module lives in `src/routes/`; the file name is the URL. Your project also ships `docs/README-MULTI-SITE.md` (URL prefix, locale and site detection) and `docs/README-SEO.md` (titles, meta tags, canonical URLs); read those for depth. ## How routes are discovered `src/routes.ts` imports `flatRoutes` from `@salesforce/storefront-next-runtime/routing` (not `@react-router/fs-routes`). It is a drop-in wrapper that: 1. scans `src/routes/` (test files are ignored), 2. merges routes from `src/extensions/<name>/routes/` (see `storefront-next:sfnext-extensions`), 3. wraps every route in the `app.url.prefix` pattern (default `/:siteId/:localeId`) through `src/app-wrapper.tsx`, and applies `app.url.seoRoutes` aliases to the product and category splats. The two SLAS callback routes (`resource.slas-reset-password-callback.ts`, `resource.slas-passwordless-login-callback.ts`) are deliberately excluded from discovery in `src/routes.ts` and registered by hand at the bare paths `/reset-password-callback` and `/passwordless-login-callback`, outside the prefix, so a single callback URL works for all sites. If you add another server-to-server callback that cannot carry a site prefix, follow the same pattern in `src/routes.ts`. ## Route tree (what exists) | Pattern | Files | Notes | |---|---|---| | `_app` layout | `_app.tsx` | header/footer shell; loads navigation; `shouldRevalidate` returns `false` | | Home, search, cart, wishlist | `_app._index.tsx`, `_app.search.tsx`, `_app.cart.tsx`, `_app.wishlist.tsx`, `_app.about-us.tsx` | | | Product detail | `_app.p.$.tsx` | splat; URL shape is build-time configurable (`url.seoRoutes`) | | Category / listing | `_app.c.$.tsx` | splat; URL shape is build-time configurable (`url.seoRoutes`) | | Account | `_app.account.tsx` (layout + auth guard), `_app.account.overview`, `.orders`, `.orders.$orderNo`, `.addresses`, `.payment-methods`, `.wishlist`, `.passkeys`, `.store-preferences` | | | Orders | `_app.order-confirmation.$orderNo.tsx`, `_app.order-lookup.*` (`results.$orderNo`, `verify.$orderNo`) | param is `$orderNo` | | `_checkout` layout | `_checkout.tsx`, `_checkout.checkout.tsx` | checkout chrome | | `_empty` layout | `_empty.tsx`, `_empty.login`, `.signup`, `.forgot-password`, `.reset-password`, `.logout`, `.maintenance`, `.oauth2.jwks`, `.preview.component`, `_empty.$.tsx` (catch-all) | no header/footer; there is no `_auth` layout | | Mutations | `action.*.ts(x)` (cart, wishlist, checkout, OTP, passkey, consent, site context...) | no UI; see `storefront-next:sfnext-data-fetching` | | Data endpoints | `resource.*.ts(x)` (recommendations, basket-products, category-products, analytics-proxy, `resource.api.client.$resource.ts`...) | no UI | Naming rules (flat routes): `.` becomes `/`, `$name` is a param, `$` alone is a splat, a leading `_` segment is a pathless layout, `_index` is the index route. Pick the layout by prefix: `_app.` for standard pages, `_checkout.` for checkout, `_empty.` for header-less pages. ## Add a page ```tsx // src/routes/_app.shipping-policy.tsx -> /shipping-policy import type { Route } from './+types/_app.shipping-policy'; import { SeoMeta } from '@/components/seo-meta'; import { Link } from '@/components/link'; import { routes } from '@/route-paths'; export async function loader({ request }: Route.LoaderArgs) { return { pageUrl: new URL(request.url).href }; } export default function ShippingPolicy({ loaderData }: Route.ComponentProps) { return ( <> <SeoMeta title="Shipping policy" description="How we ship." openGraph={{ url: loaderData.pageUrl }} /> <h1>Shipping policy</h1> <Link to={routes.cart}>Back to cart</Link> </> ); } ``` Checklist for a new page: 1. Create the file under `src/routes/` with the right layout prefix. 2. Import types from `./+types/<file-name>` (`Route.LoaderArgs`, `Route.ComponentProps`, `Route.ActionArgs`). These are generated by `pnpm typecheck` (runs `react-router typegen`) and `pnpm dev`; run one if the import is unresolved. 3. Add an entry to `routes` (page) or `resourceRoutes` (action/resource) in `src/route-paths.ts`. That file is the single source of truth for navigable paths. Keep it in sync when you rename or delete route files. 4. Render `<SeoMeta>` (and `<JsonLd>` from `@/components/json-ld` for structured data) inside the component. React 19 hoists these tags to `<head>` and they work with streaming. Use `meta` exports only when a route already does. 5. Add locale strings for user-facing text (`storefront-next:sfnext-i18n`) and a test next to the route (`storefront-next:sfnext-testing`). ## Links and navigation: always use the project wrappers ```tsx import { Link, NavLink } from '@/components/link'; import { useNavigate } from '@/hooks/use-navigate'; import { href } from 'react-router'; import { routes, routeHref, resourceRoutes } from '@/route-paths'; <Link to={routes.cart}>Cart</Link> <Link to={routeHref(routes.accountOrderDetail, { orderNo })}>Order</Link> ``` `Link`, `NavLink` and `useNavigate` from `@/components/link` and `@/hooks/use-navigate` apply the site/locale prefix (`buildUrl`). The React Router originals compile but silently produce unprefixed URLs that break multi-site routing. `AGENTS.md` makes this a hard rule. For product and category URLs use the helpers in `@/route-paths` (`createProductUrl`, `createCategoryUrl`, `createCategoryNavigationUrl`) with the SEO URL context so links follow `url.seoRoutes`. In server code (redirects), use `buildUrlFromContext(routes.login, context)` from `@/lib/url.server`: ```ts import { redirect } from 'react-router'; import { routes } from '@/route-paths'; import { buildUrlFromContext } from '@/lib/url.server'; throw redirect(buildUrlFromContext(routes.login, context)); ``` Form and fetcher `action` targets come from `resourceRoutes` (for example `resourceRoutes.cartItemAdd`), which are excluded from the site prefix via `app.url.excludeRoutes` in `config.server.ts` (`['/resource/**', '/action/**']` by default). A new `action.*` or `resource.*` route needs no prefix handling; a new page route gets it automatically. ## URL configuration `app.url` in `config.server.ts` (`prefix`, `excludeRoutes` and `seoRoutes` are protected config paths: set them in the file and rebuild, they cannot be overridden with `PUBLIC__` env vars; see `storefront-next:sfnext-configuration`) controls `prefix`, `excludeRoutes`, search-param mode, detection and `seoRoutes` (configurable product and category URL grammars). Changing the prefix or `seoRoutes` affects every link; follow `docs/README-MULTI-SITE.md` in your project rather than editing ad hoc. ## Protecting routes There is no `_auth` layout. Guard in the loader: read the session with `getAuth(context)` from `@/middlewares/auth.server` and `throw redirect(...)` to `routes.login` (see `_app.account.tsx` and `_app.wishlist.tsx`). Auth details: `storefront-next:sfnext-authentication`. ## Rules to keep in mind - Only server `loader` and `action` exports are allowed; no `clientLoader`/`clientAction`. - Throw `new Response('...', { status: 404 })` for missing content so the right HTTP status reaches crawlers. - Resource routes called from the browser should reject cross-origin requests (see `resource.recommendations.ts` for the pattern). - Deeper references: [ROUTE-CONVENTIONS.md](references/ROUTE-CONVENTIONS.md) for exports and naming, [URLS-AND-SEO-ROUTES.md](references/URLS-AND-SEO-ROUTES.md) for prefixes and SEO aliases. ## Finding more Read `AGENTS.md` in your project for the doc index. For other framework questions use `b2c docs search "storefront next routing"` (or the `docs_search` MCP tool). ## Related Skills - `storefront-next:sfnext-data-fetching` - loaders, actions, fetchers - `storefront-next:sfnext-revalidation` - `shouldRevalidate` policy per route - `storefront-next:sfnext-seo` - canonical URLs, structured data, sitemaps - `storefront-next:sfnext-page-designer` - `@PageType` and regions on routes - `storefront-next:sfnext-extensions` - routes contributed by extensions - `storefront-next:sfnext-authentication` - sessions and login flows - `storefront-next:sfnext-overview` - architecture map
Ver en GitHub