Testimonials Plugin in the Remix Supabase SaaS Starter kit

Learn how to install the Testimonials plugin in the Remix Supabase SaaS Starter kit.

This plugin allows Makerkit users to easily collect and manage testimonials from their customers. It integrates seamlessly with the existing Makerkit structure and provides both backend and frontend components.

Features

  1. Testimonial submission form and manual entry
  2. Admin panel for managing testimonials
  3. API endpoints for CRUD operations
  4. Widgets components for showing testimonials on the website

Installation

To install the plugin, run the following command:

npx @makerkit/cli plugins install

Please select the testimonial plugin from the list of available plugins.

Add the translations

Add the following to your apps/web/lib/i18n/locales/en/testimonials.json file:

apps/web/lib/i18n/locales/en/testimonials.json
{
"welcomeMessage": "We'd love to hear your feedback!",
"welcomeMessageDescription": "Your opinion helps us improve our service.",
"textButtonText": "Write a review",
"videoButtonText": "Record a video review",
"backButtonText": "Choose a different review type",
"customerName": "Your Name",
"testimonial": "Testimonial",
"rating": "Rating",
"submitting": "Submitting...",
"submitTestimonial": "Submit Testimonial",
"errorTitle": "Sorry, something went wrong",
"errorDescription": "Apologies, we were unable to submit your video review. Please try again later.",
"customerNameDescription": "Your name will be displayed with your video review",
"recording": "Recording... {{timer}}",
"startRecording": "Start Recording",
"stopRecording": "Stop Recording",
"discardAndRetry": "Discard and retry",
"successTitle": "Thank you!",
"successDescription": "Your feedback helps us improve our services. We appreciate your time!",
"wallOfLove": "Wall of Love",
"videoTestimonialBy": "Video testimonial by {{customerName}}",
"clickToPlay": "Click to play video testimonial",
"videoTagNotSupported": "Your browser does not support the video tag.",
"moreTestimonials": "{{count}} more testimonials"
}

Now, add the namespace to the loaded translations in your apps/web/lib/i18n/i18n.settings.ts file:

apps/web/lib/i18n/i18n.settings.ts
export const defaultI18nNamespaces = [
// ... your existing namespaces
'testimonials',
];

Migration

Create a new migration file by running the following command:

pnpm --filter web supabase migration new testimonials

And place the content you can see at packages/plugins/testimonial/migrations/migration.sql into the newly created file.

Then run the migration:

pnpm run supabase:web:reset

And update the types:

pnpm run supabase:web:typegen

Once the plugin is added to your repository, please install it as a dependency in your application in the package.json file of apps/web:

{
"dependencies": {
"@kit/testimonial": "workspace:*"
}
}

Now run the following command to install the plugin:

pnpm i

You can now add the Admin pages from where you can manage the testimonials. To do so, add the following code to the apps/web/app/routes/admin.testimonials._index/route.tsx file:

import { LoaderFunctionArgs } from '@remix-run/server-runtime';
import {
testimonialsAction,
testimonialsLoader,
} from '@kit/testimonial/admin/api';
import { TestimonialsPage } from '@kit/testimonial/admin/pages';
export const loader = (args: LoaderFunctionArgs) => {
return testimonialsLoader(args);
};
export const action = (args: LoaderFunctionArgs) => {
return testimonialsAction(args);
};
export default TestimonialsPage;

And now the testimonial's page at apps/web/app/routes/admin.testimonials.$id._index/route.ts:

import { LoaderFunctionArgs } from '@remix-run/server-runtime';
import {
TestimonialPage,
} from '@kit/testimonial/admin/pages';
import {
testimonialLoader,
testimonialAction,
} from '@kit/testimonial/admin/api';
export const loader = (args: LoaderFunctionArgs) => {
return testimonialLoader(args);
};
export const action = (args: LoaderFunctionArgs) => {
return testimonialAction(args);
};
export default TestimonialPage;

Add the sidebar item as well at apps/web/app/routes/admin/_components/admin-sidebar.tsx:

<SidebarItem
path={'/admin/testimonials'}
Icon={<StarIcon className={'h-4'} />}
>
Testimonials
</SidebarItem>

You can now run the application and navigate to the Admin panel to manage the testimonials.

Displaying the Testimonial Form

To display the testimonial form on your website, you can import the form component from the plugin and use it in your page.

Create a new component, and import the form:

import { useState } from 'react';
import {
TestimonialContainer,
TestimonialForm,
TestimonialSuccessMessage,
VideoTestimonialForm,
} from '@kit/testimonial/client';
export function Testimonial() {
const [success, setSuccess] = useState(false);
const onSuccess = () => setSuccess(true);
if (success) {
return <SuccessMessage />;
}
return (
<TestimonialContainer
className={
'w-full max-w-md rounded-lg border bg-background p-8 shadow-xl'
}
welcomeMessage={<WelcomeMessage />}
enableTextReview={true}
enableVideoReview={true}
textReviewComponent={<TestimonialForm onSuccess={onSuccess} />}
videoReviewComponent={<VideoTestimonialForm onSuccess={onSuccess} />}
textButtonText="Write your thoughts"
videoButtonText="Share a video message"
backButtonText="Switch review method"
/>
);
}
function SuccessMessage() {
return (
<div
className={
'w-full max-w-md rounded-lg border bg-background p-8 shadow-xl'
}
>
<div className="flex flex-col items-center space-y-4 text-center">
<div className="space-y-1">
<h1 className="text-2xl font-semibold">
Thank you for your feedback!
</h1>
<p className="text-muted-foreground">
Your review has been submitted successfully.
</p>
</div>
<div>
<TestimonialSuccessMessage />
</div>
</div>
</div>
);
}
function WelcomeMessage() {
return (
<div className="flex flex-col items-center space-y-1 text-center">
<h1 className="text-2xl font-semibold">
We&apos;d love to hear your feedback!
</h1>
<p className="text-muted-foreground">
Your opinion helps us improve our service.
</p>
</div>
);
}

Please customize the components as needed to fit your website's design.

API Endpoints

Please add the GET endpoint to fetch the testimonials at apps/web/app/routes/api.testimonials._index/route.ts:

import { ActionFunctionArgs } from '@remix-run/server-runtime';
import { createTestimonialsLoader, createAddTestimonialAction } from '@kit/testimonial/server';
export const action = ({ request }: ActionFunctionArgs) => {
return createAddTestimonialAction(request);
};
export const loader = ({ request }: ActionFunctionArgs) => {
return createTestimonialsLoader(request);
};

Widgets

To display the testimonials on your website, you can use the following widget:

import { TestimonialWallWidget } from '@kit/testimonial/widgets';
export default function TestimonialWidgetPage() {
return (
<div className={'flex h-full w-screen flex-1 flex-col items-center py-16'}>
<TestimonialWallWidget />
</div>
);
}

Done! You now have a fully functional Testimonial Collection plugin integrated with your Makerkit application.