# Brands page (https://docs.salla.dev/twilight/react/routes/brands)



<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 every brand's logo, grouped by first letter, with a letter bar that jumps to each group. Each logo opens the [brand page](https://docs.salla.dev/twilight/react/routes/brand). Customise this route to change the title or draw the groups yourself.

## URL [#url]

| Pattern            | Example      |
| ------------------ | ------------ |
| `/brands`          | `/brands`    |
| `/{locale}/brands` | `/ar/brands` |

The only param is the optional `locale` ([locale prefix](https://docs.salla.dev/twilight/react/routes/home#locale-prefix)). There are no search params.

### Try it [#try-it]

This is the brands list as the engine renders it, running against the demo store. Switch the language or the width.

<RoutePreview path="/brands" pattern="/{locale}/brands" />

## Route file [#route-file]

```tsx title="app/routes/brands.tsx"
// @auto-generated
import { createFileRoute } from '@tanstack/react-router';
import { Brands } from '@salla.sa/twilight-theme-engine/routes/brands';
import type { BrandsPageProps } from '@salla.sa/twilight-theme-engine/routes/brands';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/brands')({
  loader: ({ params }): Promise<BrandsPageProps> => Brands.loader({ locale: params.locale }),
  head: withHead(Brands),
  component: BrandsComponent,
});

function BrandsComponent() {
  const data: BrandsPageProps = Route.useLoaderData();
  return <Brands.Component {...data} />;
}
```

To take the page over, write your own file and map the path in `app/routes.ts`: `route('/brands', 'my-brands.tsx')`. See [Fork a built-in route](https://docs.salla.dev/twilight/react/recipes/fork-a-built-in-route).

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

This keeps the engine loader and component and adds a suffix to the title.

```tsx title="app/routes/my-brands.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { Brands } from '@salla.sa/twilight-theme-engine/routes/brands';
import type { BrandsPageProps } from '@salla.sa/twilight-theme-engine/routes/brands';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/brands')({
  loader: ({ params }): Promise<BrandsPageProps> => Brands.loader({ locale: params.locale }),
  head: withHead(Brands, (head) => ({ ...head, title: `${head.title} | Official store` })),
  component: BrandsComponent,
});

function BrandsComponent() {
  const data: BrandsPageProps = Route.useLoaderData();
  return <Brands.Component {...data} />;
}
```

`Brands.loader` also takes an optional second argument, `extend(data)`, that returns fields to merge into the loader data.

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

`BrandsPageProps`:

| Field        | Type                        | Description                                                                            |
| ------------ | --------------------------- | -------------------------------------------------------------------------------------- |
| `page`       | `Page`                      | `title` is the translated "Brands".                                                    |
| `brands`     | `Brand[]`                   | The first page of brands (`id`, `name`, `logo`, `url`, `ar_char`, `en_char` and more). |
| `pagination` | `{ next?: string \| null }` | Set while more pages exist.                                                            |

The first request loads this on the server. `Brands.Component` then fetches the remaining pages in the browser, and groups every brand by its first letter (`ar_char` when the locale is `ar`, `en_char` otherwise; brands without one go under `#`). Groups are sorted by letter. `Brands.Component` is loaded lazily; render it the way the generated route does. See [Brands API](https://docs.salla.dev/twilight/react/api/modules/brands).

The page has two [hook slots](https://docs.salla.dev/twilight/react/guide/hooks-and-slots) around the groups: `brands:index.items.start` and `brands:index.items.end`.

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

Title is the translated "Brands", plus hreflang links. There is no description, canonical or Open Graph tag. See [SEO and head](https://docs.salla.dev/twilight/react/guide/seo-and-head).

## Edge cases [#edge-cases]

* **No brands.** An empty `brands` list shows an empty state with a link home. It is not a 404.
* **More than one page of brands.** The letter bar and groups fill in as the browser loads the other pages. A custom page that renders only `brands` shows only the first page.
* **Letter bar.** It lists only letters that have brands, and sticks to the top after 200px of scrolling.
* **Request failure.** The error page is shown.

## See also [#see-also]

* [Brand page](https://docs.salla.dev/twilight/react/routes/brand) and [Brand products](https://docs.salla.dev/twilight/react/routes/brand-products)
* [Routes and pages](https://docs.salla.dev/twilight/react/guide/routes-and-pages)
* [Routes overview](https://docs.salla.dev/twilight/react/routes)
