Product reviews

The page that lists shoppers' reviews of the store's products, which store menus link to.

Framework: TanStack Start

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

The customer reads what shoppers wrote about the store's products, all on one page. It is Twig's pages/reviews, the page a store menu's "Product Reviews" link opens. Everyone can open it. The engine serves this route itself, so your theme has no file for it.

URL

PatternExample
/{-$locale}/reviews/reviews · /ar/reviews

Optional param: locale (locale prefix).

Try it

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

/ar/reviewsOpen
Route
/{-$locale}/reviews
This address becomes
  • locale = ar
  • path = /reviews

Route file

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

reviews.tsx (served by the engine)
// @auto-generated
import { createFileRoute } from '@tanstack/react-router';
import { Reviews } from '@salla.sa/twilight-theme-engine/routes/testimonials';
import type { ReviewsPageProps } from '@salla.sa/twilight-theme-engine/routes/testimonials';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/reviews')({
  loader: ({ params }): Promise<ReviewsPageProps> => Reviews.loader({ locale: params.locale }),
  head: withHead(Reviews),
  component: ReviewsComponent,
});

function ReviewsComponent() {
  const data: ReviewsPageProps = Route.useLoaderData();
  return <Reviews.Component {...data} />;
}

To take the page over, add app/routes/reviews.tsx without the // @auto-generated line. The build then uses your file instead of the engine's. See Fork a built-in route.

A customised version

Set a fixed title with the loader's extend argument, and wrap the engine page in your own element:

app/routes/reviews.tsx
import { createFileRoute } from '@tanstack/react-router';
import { Reviews } from '@salla.sa/twilight-theme-engine/routes/testimonials';
import type { ReviewsPageProps } from '@salla.sa/twilight-theme-engine/routes/testimonials';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/reviews')({
  loader: ({ params }): Promise<ReviewsPageProps> =>
    Reviews.loader({ locale: params.locale }, (data) => ({
      page: { ...data.page, title: 'What shoppers say about our products' },
    })),
  head: withHead(Reviews),
  component: function ReviewsRoute() {
    const data: ReviewsPageProps = Route.useLoaderData();
    return (
      <section className="my-reviews">
        <Reviews.Component {...data} />
      </section>
    );
  },
});

What it loads

The loader makes no API call. It returns { page: { slug: 'reviews', title, breadcrumbs } }, with the title from the common.titles.reviews translation and breadcrumbs of Home, then this page. ReviewsPage renders the breadcrumb and Salla's <salla-reviews-page> web component, which loads, sorts and pages the reviews in the browser, so they are not in the server HTML.

The head sets the title and language alternates.

Edge cases

  • Empty list. Handled by <salla-reviews-page>, not by this route.
  • Lazy. Reviews.Component (also exported as ReviewsPage) is code-split: outside a route, wrap it in <Suspense>.

See also

On this page