Account

The shared /account layout that frames every signed-in page, and how a child page shapes it.

Framework: TanStack Start

This page is written for TanStack Start, the default and currently supported framework. See what depends on the framework.

Every signed-in page (profile, orders, wallet and the rest) shows inside one frame: a breadcrumb, a title, and a user menu on large screens. That frame is the /account layout. Read this page when you want to retitle a page in the frame, show your own skeleton while it loads, or style account pages differently from the rest of the store.

URL

/account is a layout route: it has no page of its own. It wraps whichever child page matches.

URLRenders
/accountthe frame with an empty body, because no child matches
/account/profile, /ar/account/profilethe frame around Profile

The children are profile, wishlist, wallet, notifications, settings, orders and one order. Pending orders is also nested here, but it only redirects.

The only param is the optional locale ({-$locale}). See Languages and RTL.

Route file

There is no app/routes/account.tsx in your project. The engine registers the layout itself, so you cannot take it over by copying a file. What it does is simple: it reads page from the deepest child's loader data and hands it to CustomerLayout, with the child inside.

Shape the frame from a child route

The frame takes its title and breadcrumb from the child's page ({ title, slug }). To change them, return a new page from the loader's extend argument:

app/routes/account.profile.tsx
import { createFileRoute } from '@tanstack/react-router';
import { Profile } from '@salla.sa/twilight-theme-engine/routes/account';
import type { ProfilePageProps } from '@salla.sa/twilight-theme-engine/routes/account';
import { CustomerPageSkeleton } from '@salla.sa/twilight-theme-engine/skeleton';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/account/profile')({
  loader: ({ params }): Promise<ProfilePageProps> =>
    Profile.loader({ locale: params.locale }, (data) => ({
      page: { ...data.page, title: 'My details' },
    })),
  head: withHead(Profile),
  pendingComponent: () => <CustomerPageSkeleton />,
  component: function ProfileRoute() {
    const data: ProfilePageProps = Route.useLoaderData();
    return <Profile.Component {...data} />;
  },
});

What the layout provides

  • The breadcrumb and <h1>, from the child's page. The profile page also gets the avatar uploader above the menu.
  • A customer class on <body>, so you can scope styles to account pages.
  • The user menu sidebar, on large screens only.
  • A skeleton while a child loads: CustomerLayoutSkeleton, or your own component registered under the key account:layout-pending.

What it loads

Nothing. Each child loads its own data and decides whether a token is needed. The layout does not redirect a signed-out customer and sets no head tags; each child sets its own title and language alternates.

Edge cases

  • /account on its own shows the frame with an empty body and no title. Link to a child page, such as /account/orders.
  • Signed out. Handled per child: each throws unauthorized(), which sends a guest to the home page with ?intended_to=, where the Salla SDK opens the sign-in form. See Authentication and scope.

See also

On this page