# Brand page (https://docs.salla.dev/twilight/react/routes/brand)



<Callout title="Framework: TanStack Start">
  This page is written for TanStack Start, the default and currently supported framework. [See what depends on the framework](https://docs.salla.dev/twilight/react/start/frameworks).
</Callout>

The customer sees one brand's banner, logo and description, with its products below. They reach it from the [brands index](https://docs.salla.dev/twilight/react/routes/brands) or a brand link on a product. Customise this route to add a canonical tag, change the title, or render the list with your own component.

## URL [#url]

| Pattern                | Example         |
| ---------------------- | --------------- |
| `/brands/$id`          | `/brands/77`    |
| `/{locale}/brands/$id` | `/en/brands/77` |

The short form `/$slug/brand-{$id}` redirects here ([Brand products](https://docs.salla.dev/twilight/react/routes/brand-products)).

### Params [#params]

| Name     | Type                  | Example | Description                                             |
| -------- | --------------------- | ------- | ------------------------------------------------------- |
| `id`     | `string`              | `77`    | The brand id. There is no slug segment.                 |
| `locale` | `string \| undefined` | `en`    | Optional ([locale prefix](https://docs.salla.dev/twilight/react/routes/home#locale-prefix)). |

### Search params [#search-params]

| Name   | Type     | Example    | Description                                                                                                                                               |
| ------ | -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sort` | `string` | `bestSell` | Optional. The loader uses `ourSuggest` when absent.                                                                                                       |
| `page` | `number` | `2`        | Optional. Values of 1 or less are dropped. The API pages only by its own cursor, so the loader ignores a number and the list starts from the first batch. |

### Try it [#try-it]

This is a brand as the engine renders it, running against the demo store. Switch the language or the width. Change the id to open another one.

<RoutePreview path="/brands/{id}" pattern="/{locale}/brands/$id" controls="{ id: { label: 'Brand id', default: '1146128145' } }" />

## Route file [#route-file]

The engine writes this file into its own `.twilight/` folder, not into `app/routes/`:

```tsx title="brands.$id.tsx (served by the engine)"
// @auto-generated
import { createFileRoute } from '@tanstack/react-router';
import { ProductListing, listingSearch } from '@salla.sa/twilight-theme-engine/routes/product-listing';
import type { ProductListLoaderData } from '@salla.sa/twilight-theme-engine/routes/product-listing';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/brands/$id')({
  ...listingSearch,
  loader: ({ deps, params }): Promise<ProductListLoaderData> =>
    ProductListing.loader({
      params: { source: 'brands', id: params.id },
      search: deps,
      locale: params.locale,
    }),
  head: withHead(ProductListing),
  pendingComponent: () => <ProductListing.Pending hideFilters />,
  component: ProductListingComponent,
});

function ProductListingComponent() {
  const data: ProductListLoaderData = Route.useLoaderData();
  return <ProductListing.Component {...data} />;
}
```

To take the page over, add `app/routes/brands.$id.tsx` without the `// @auto-generated` line, or write your own file and map the path in `app/routes.ts`: `route('/brands/$id', 'brands-page.tsx')`. See [Fork a built-in route](https://docs.salla.dev/twilight/react/recipes/fork-a-built-in-route). To restyle every product list at once, register a page as `product:list-page` instead; see [Replace the product list page](https://docs.salla.dev/twilight/react/recipes/replace-the-product-card#replace-the-whole-product-list-page).

### A customised version [#a-customised-version]

This adds a suffix to the title and a line above the engine list.

```tsx title="app/routes/brand-page.tsx"
import { createFileRoute } from '@tanstack/react-router';
import {
  ProductListing,
  listingSearch,
  type ProductListLoaderData,
} from '@salla.sa/twilight-theme-engine/routes/product-listing';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/brands/$id')({
  ...listingSearch,
  loader: ({ deps, params }): Promise<ProductListLoaderData> =>
    ProductListing.loader({
      params: { source: 'brands', id: params.id },
      search: deps,
      locale: params.locale,
    }),
  head: withHead(ProductListing, (head, _ctx, data) => ({
    ...head,
    title: `${data.page.title} | Official store`,
  })),
  component: ListComponent,
});

function ListComponent() {
  const data: ProductListLoaderData = Route.useLoaderData();
  return (
    <>
      <p className="container">{data.products.length} products on this page</p>
      <ProductListing.Component {...data} />
    </>
  );
}
```

## What it loads [#what-it-loads]

`ProductListLoaderData`, the same shape as on the [category page](https://docs.salla.dev/twilight/react/routes/category#what-it-loads). For brands:

* The loader fetches the brand and its first products together on the server. `source.entity` is the `Brand` (name, logo, banner, description, `url`).
* `query.filters` is `false`, so there is no filter panel.
* Breadcrumbs are Home, then the brand name.
* The page draws the banner, logo, name and description (when set) above the list.

The page has the same [hook slots](https://docs.salla.dev/twilight/react/guide/hooks-and-slots) as every product list (`product:list.*`).

## Head and SEO [#head-and-seo]

Title is the brand name and description is `Browse {name}`, with Open Graph and Twitter cards and hreflang links. Unlike categories and tags, there is no canonical tag and no social image. Add them with a `withHead` extension if you need them.

## Edge cases [#edge-cases]

* **Unknown brand.** If a request fails or the brand comes back empty, the loader throws a not-found error and the [not-found page](https://docs.salla.dev/twilight/react/routes/not-found) renders.
* **Brand without products.** The list shows its empty state. There is no 404.
* **Short URLs.** `/nike/brand-77` redirects here and keeps the locale.

## See also [#see-also]

* [Brands index](https://docs.salla.dev/twilight/react/routes/brands) and [Brand products](https://docs.salla.dev/twilight/react/routes/brand-products)
* [Category page](https://docs.salla.dev/twilight/react/routes/category)
* [Fork a built-in route](https://docs.salla.dev/twilight/react/recipes/fork-a-built-in-route)
* [Routes overview](https://docs.salla.dev/twilight/react/routes)
