Testimonials

The page that lists customer reviews of the store with a sort control.

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 customers wrote about the store as a whole (not one product), and can sort the reviews. Everyone can open it. Customise it to retitle the page or wrap it in your own layout.

URL

PatternExample
/{-$locale}/testimonials/testimonials, /ar/testimonials?sort=top_rating
ParamTypeNotes
localestring (optional)ar in the example above
sort (search)stringlatest (default), oldest, top_rating or bottom_rating. The route does not validate it; the page component reads and writes it.

Try it

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

/ar/testimonialsOpen
Route
/{-$locale}/testimonials
This address becomes
  • locale = ar
  • path = /testimonials

Route file

app/routes/testimonials.tsx
// @auto-generated
import { createFileRoute } from '@tanstack/react-router';
import { Testimonials } from '@salla.sa/twilight-theme-engine/routes/testimonials';
import type { TestimonialsPageProps } from '@salla.sa/twilight-theme-engine/routes/testimonials';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/testimonials')({
  loader: ({ params }): Promise<TestimonialsPageProps> =>
    Testimonials.loader({ locale: params.locale }),
  head: withHead(Testimonials),
  component: TestimonialsComponent,
});

function TestimonialsComponent() {
  const data: TestimonialsPageProps = Route.useLoaderData();
  return <Testimonials.Component {...data} />;
}

To take the page over, delete the // @auto-generated line and edit the file. 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/testimonials.tsx
export const Route = createFileRoute('/{-$locale}/testimonials')({
  loader: ({ params }): Promise<TestimonialsPageProps> =>
    Testimonials.loader({ locale: params.locale }, (data) => ({
      page: { ...data.page, title: 'What our customers say' },
    })),
  head: withHead(Testimonials),
  component: function TestimonialsRoute() {
    const data: TestimonialsPageProps = Route.useLoaderData();
    return (
      <section className="my-reviews">
        <Testimonials.Component {...data} />
      </section>
    );
  },
});

What it loads

The loader makes no API call. It returns { page: { slug, title } }, with the title from the blocks.home.testimonials translation. The reviews load in the browser through the SallaComments component, so they are not in the server HTML.

The head sets the title, description and language alternates.

Edge cases

  • Sorting. The page reads ?sort= on mount. Each change rewrites the URL without a navigation (the loader does not run again) and reloads the list. An unknown value is passed through as is.
  • Empty list. Handled by SallaComments, not by this route.

See also

On this page