Next.js Supabase V3 (#463)
Version 3 of the kit: - Radix UI replaced with Base UI (using the Shadcn UI patterns) - next-intl replaces react-i18next - enhanceAction deprecated; usage moved to next-safe-action - main layout now wrapped with [locale] path segment - Teams only mode - Layout updates - Zod v4 - Next.js 16.2 - Typescript 6 - All other dependencies updated - Removed deprecated Edge CSRF - Dynamic Github Action runner
This commit is contained in:
committed by
GitHub
parent
4912e402a3
commit
7ebff31475
70
docs/plugins/feedback-plugin.mdoc
Normal file
70
docs/plugins/feedback-plugin.mdoc
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
status: "published"
|
||||
title: 'Add a Feedback Widget plugin to your Next.js Supabase SaaS Starter kit'
|
||||
label: 'Feedback Widget'
|
||||
order: 5
|
||||
description: 'Add a Feedback Widget plugin to your Next.js Supabase SaaS Starter kit'
|
||||
---
|
||||
|
||||
This plugin is a lighter version of the Roadmap plugin. It is recommended to install the Roadmap plugin if you need more features.
|
||||
|
||||
The feedback plugin allows you to add a feedback widget to your app. Users can provide feedback on your app, and you can view and manage feedback submissions in the admin panel.
|
||||
|
||||
### Installation
|
||||
|
||||
Pull the plugin from the main repository:
|
||||
|
||||
```
|
||||
npx @makerkit/cli@latest plugins add feedback
|
||||
```
|
||||
|
||||
The codemod will automatically:
|
||||
- Add the `@kit/feedback` dependency and install packages
|
||||
- Add the feedback sidebar item to the admin panel
|
||||
- Create the translation file at `apps/web/i18n/messages/en/feedback.json`
|
||||
- Add the `feedback` namespace to your i18n settings
|
||||
- Create the Supabase migration file for the feedback table
|
||||
|
||||
### Run the migrations
|
||||
|
||||
After installation, run the migration and regenerate types:
|
||||
|
||||
```
|
||||
pnpm run supabase:web:reset
|
||||
pnpm run supabase:web:typegen
|
||||
```
|
||||
|
||||
### Import the component
|
||||
|
||||
Now, you can import the component from the plugin:
|
||||
|
||||
```tsx
|
||||
import { FeedbackPopup } from '@kit/feedback';
|
||||
```
|
||||
|
||||
And use it in your app:
|
||||
|
||||
```tsx
|
||||
<FeedbackPopup>
|
||||
<Button>Gimme feedback</Button>
|
||||
</FeedbackPopup>
|
||||
```
|
||||
|
||||
You can also import the form alone - so you can customize its appearance:
|
||||
|
||||
```tsx
|
||||
import {FeedbackForm} from '@kit/feedback';
|
||||
```
|
||||
|
||||
And use it in your app:
|
||||
|
||||
```tsx
|
||||
<FeedbackForm/>
|
||||
```
|
||||
|
||||
## Admin Panel
|
||||
|
||||
The admin pages and sidebar item are automatically set up by the CLI. You can find them at:
|
||||
|
||||
- `apps/web/app/[locale]/admin/feedback/page.tsx` — Feedback submissions list
|
||||
- `apps/web/app/[locale]/admin/feedback/[id]/page.tsx` — Submission detail page
|
||||
27
docs/plugins/installing-plugins.mdoc
Normal file
27
docs/plugins/installing-plugins.mdoc
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
status: "published"
|
||||
title: 'Installing Plugins in the Next.js Supabase SaaS Starter kit'
|
||||
label: 'Installing Plugins'
|
||||
order: 0
|
||||
description: 'Learn how to install plugins in the Next.js Supabase SaaS Starter kit.'
|
||||
---
|
||||
|
||||
Plugins are placed into a separate repository that mirrors the original repository structure. This allows us to build the plugins using the same files and structure as the main repository.
|
||||
|
||||
You may wonder why we don't include the plugins in the main repository. The reason is that plugins are optional and may not be needed by all users.
|
||||
|
||||
By keeping them separate, we can keep the main repository clean and focused on the core functionality. Instead you can install the plugins you need when you need them.
|
||||
|
||||
## Installing Plugins
|
||||
|
||||
To install a plugin, you can use the Makerkit CLI:
|
||||
|
||||
```bash
|
||||
npx @makerkit/cli@latest plugins add
|
||||
```
|
||||
|
||||
This command will prompt you to select a plugin to install. Once selected, the plugin will be installed in your project.
|
||||
|
||||
## How Makerkit installs plugins in your project
|
||||
|
||||
We use the Shadcn CLI to create a registry of plugins that are available for your variant. The Makerkit CLI uses the registry to download the plugin files and install them in your project. We also use [Codemod](https://codemod.com) to wire up the plugin in your project, so you don't have to do anything manually.
|
||||
75
docs/plugins/roadmap-plugin.mdoc
Normal file
75
docs/plugins/roadmap-plugin.mdoc
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
status: "published"
|
||||
title: 'Roadmap Plugin in the Next.js Supabase SaaS Starter kit'
|
||||
label: 'Roadmap Plugin'
|
||||
order: 2
|
||||
description: 'Learn how to install the Roadmap plugin in the Next.js Supabase SaaS Starter kit.'
|
||||
---
|
||||
|
||||
This plugin allows you to create a roadmap for your project and display it on your website.
|
||||
|
||||
Your users can see what features are planned, in progress, and completed and suggest new features or comment on existing ones.
|
||||
|
||||
## Functionality
|
||||
|
||||
The plugin provides the following functionality:
|
||||
|
||||
1. Display the feature requests on the website.
|
||||
2. Allow users to suggest new features.
|
||||
3. Allow users to comment on existing features.
|
||||
4. Display the Feature Requests in the Admin panel.
|
||||
5. Allow Admins to manage the Feature Requests, update their status, and delete them.
|
||||
6. Allow Admins to manage the comments on the Feature Requests.
|
||||
|
||||
## Installation
|
||||
|
||||
To install the plugin, run the following command:
|
||||
|
||||
```bash
|
||||
npx @makerkit/cli plugins add
|
||||
```
|
||||
|
||||
Since this plugin depends on the Kanban plugin, you need to install both. Please select the `kanban` plugin from the list of available plugins.
|
||||
|
||||
Then, please select the `roadmap` plugin from the list of available plugins.
|
||||
|
||||
The codemod will automatically:
|
||||
- Add the `@kit/roadmap` dependency and install packages
|
||||
- Create the translation file at `apps/web/i18n/messages/en/roadmap.json`
|
||||
- Add the `roadmap` namespace to your i18n settings
|
||||
- Add the roadmap sidebar item to the admin panel
|
||||
- Create the Supabase migration file for the roadmap tables
|
||||
|
||||
### Run the migrations
|
||||
|
||||
After installation, run the migration and regenerate types:
|
||||
|
||||
```bash
|
||||
pnpm run supabase:web:reset
|
||||
pnpm run supabase:web:typegen
|
||||
```
|
||||
|
||||
## Displaying the Roadmap and Feature Requests
|
||||
|
||||
To display the roadmap and feature requests on your website, add the following code to the `apps/web/app/[locale]/(marketing)/roadmap/page.tsx` file:
|
||||
|
||||
```tsx
|
||||
import { RoadmapPage } from "@kit/roadmap/server";
|
||||
|
||||
export default RoadmapPage;
|
||||
```
|
||||
|
||||
Let's now add the comments GET route at `apps/web/app/[locale]/(marketing)/roadmap/comments/route.ts`:
|
||||
|
||||
```tsx
|
||||
import { createFetchCommentsRouteHandler } from '@kit/roadmap/route-handler';
|
||||
|
||||
export const GET = createFetchCommentsRouteHandler;
|
||||
```
|
||||
|
||||
## Admin Pages
|
||||
|
||||
The admin pages and sidebar item are automatically set up by the CLI. You can find them at:
|
||||
|
||||
- `apps/web/app/[locale]/admin/roadmap/page.tsx` — Feature requests list
|
||||
- `apps/web/app/[locale]/admin/roadmap/[id]/page.tsx` — Feature request detail page
|
||||
163
docs/plugins/testimonials-plugin.mdoc
Normal file
163
docs/plugins/testimonials-plugin.mdoc
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
status: "published"
|
||||
title: 'Testimonials Plugin in the Next.js Supabase SaaS Starter kit'
|
||||
label: 'Testimonials Plugin'
|
||||
order: 3
|
||||
description: 'Learn how to install the Testimonials plugin in the Next.js 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:
|
||||
|
||||
```bash
|
||||
npx @makerkit/cli plugins add testimonial
|
||||
```
|
||||
|
||||
The codemod will automatically:
|
||||
- Add the `@kit/testimonial` dependency and install packages
|
||||
- Create the translation file at `apps/web/i18n/messages/en/testimonials.json`
|
||||
- Add the `testimonials` namespace to your i18n settings
|
||||
- Add the testimonials sidebar item to the admin panel
|
||||
- Create the Supabase migration file for the testimonials table
|
||||
|
||||
### Run the migrations
|
||||
|
||||
After installation, run the migration and regenerate types:
|
||||
|
||||
```bash
|
||||
pnpm run supabase:web:reset
|
||||
pnpm run supabase:web:typegen
|
||||
```
|
||||
|
||||
The admin pages and sidebar item are automatically set up by the CLI. You can find them at:
|
||||
|
||||
- `apps/web/app/[locale]/admin/testimonials/page.tsx` — Testimonials list
|
||||
- `apps/web/app/[locale]/admin/testimonials/[id]/page.tsx` — Testimonial detail page
|
||||
|
||||
## 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:
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
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'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 and POST endpoints to fetch the testimonials at `apps/web/app/api/testimonials/route.ts`:
|
||||
|
||||
```ts
|
||||
import {
|
||||
createTestimonialsRouteHandler,
|
||||
createVideoTestimonialRouteHandler,
|
||||
} from '@kit/testimonial/server';
|
||||
|
||||
export const GET = createTestimonialsRouteHandler;
|
||||
export const POST = createVideoTestimonialRouteHandler;
|
||||
```
|
||||
|
||||
## Widgets
|
||||
|
||||
To display the testimonials on your website, you can use the following widget:
|
||||
|
||||
```tsx
|
||||
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.
|
||||
185
docs/plugins/waitlist-plugin.mdoc
Normal file
185
docs/plugins/waitlist-plugin.mdoc
Normal file
@@ -0,0 +1,185 @@
|
||||
---
|
||||
status: "published"
|
||||
title: 'Add a Waitlist to the Next.js Supabase SaaS Starter kit'
|
||||
label: 'Waitlist'
|
||||
order: 1
|
||||
description: 'Add a waitlist to your Next.js Supabase SaaS Starter kit to collect emails from interested users.'
|
||||
---
|
||||
|
||||
In this guide, you will learn how to add a waitlist to your Next.js Supabase SaaS Starter kit to collect emails from interested users. This feature is useful for building an audience before launching your product.
|
||||
|
||||
This plugin allows you to create a waitlist for your app. Users can sign up for the waitlist and receive an email when the app is ready.
|
||||
|
||||
### How it works
|
||||
|
||||
1. You disable sign up in your app from Supabase. This prevents any user from using the public API to sign up.
|
||||
2. We create a new table in Supabase called `waitlist`. Users will sign up for the waitlist and their email will be stored in this table.
|
||||
3. When you want to enable a sign up for a user, mark users as `approved` in the `waitlist` table.
|
||||
4. The database trigger will create a new user in the `auth.users` table and send an email to the user with a link to set their password.
|
||||
5. The user can now sign in to the app and update their password.
|
||||
6. User gets removed from the waitlist as soon as the email is sent.
|
||||
|
||||
### Installation
|
||||
|
||||
#### Get the plugin using the CLI
|
||||
|
||||
Please run the following command in your terminal:
|
||||
|
||||
```bash
|
||||
npx @makerkit/cli@latest plugins add waitlist
|
||||
```
|
||||
|
||||
After completed, the CLI will install the plugin at `packages/plugins/waitlist`.
|
||||
|
||||
The codemod will automatically:
|
||||
- Add the `@kit/waitlist` dependency and install packages
|
||||
- Replace the sign-up form with the waitlist form
|
||||
- Add the waitlist translations to your `auth.json` locale file
|
||||
- Create the Supabase migration file for the waitlist table
|
||||
|
||||
#### Run the migrations
|
||||
|
||||
After installation, run the migration and regenerate types:
|
||||
|
||||
```bash
|
||||
pnpm run supabase:web:reset
|
||||
pnpm run supabase:web:typegen
|
||||
```
|
||||
|
||||
#### Adding the Database Webhook to listen for new signups
|
||||
|
||||
Let's extend the DB handler at `apps/web/app/api/db/webhook/route.ts`. This handler will listen for new signups and send an email to the user:
|
||||
|
||||
```tsx
|
||||
import { getDatabaseWebhookHandlerService } from '@kit/database-webhooks';
|
||||
import { getServerMonitoringService } from '@kit/monitoring/server';
|
||||
import { enhanceRouteHandler } from '@kit/next/routes';
|
||||
|
||||
import appConfig from '~/config/app.config';
|
||||
import pathsConfig from '~/config/paths.config';
|
||||
|
||||
/**
|
||||
* @name POST
|
||||
* @description POST handler for the webhook route that handles the webhook event
|
||||
*/
|
||||
export const POST = enhanceRouteHandler(
|
||||
async ({ request }) => {
|
||||
const service = getDatabaseWebhookHandlerService();
|
||||
|
||||
try {
|
||||
const signature = request.headers.get('X-Supabase-Event-Signature');
|
||||
|
||||
if (!signature) {
|
||||
return new Response('Missing signature', { status: 400 });
|
||||
}
|
||||
|
||||
const body = await request.clone().json();
|
||||
|
||||
// handle the webhook event
|
||||
await service.handleWebhook({
|
||||
body,
|
||||
signature,
|
||||
async handleEvent(payload) {
|
||||
if (payload.table === 'waitlist' && payload.record.approved) {
|
||||
const { handleApprovedUserChange } = await import(
|
||||
'@kit/waitlist/server'
|
||||
);
|
||||
|
||||
const inviteToken = payload.record.invite_token;
|
||||
|
||||
const redirectToUrl = new URL(
|
||||
pathsConfig.auth.passwordUpdate,
|
||||
appConfig.url,
|
||||
);
|
||||
|
||||
if (inviteToken) {
|
||||
const next = encodeURI(
|
||||
pathsConfig.app.joinTeam + '?invite_token=' + inviteToken,
|
||||
);
|
||||
|
||||
redirectToUrl.searchParams.append('callback', next);
|
||||
}
|
||||
|
||||
const redirectTo = redirectToUrl.toString();
|
||||
|
||||
await handleApprovedUserChange({
|
||||
email: payload.record.email,
|
||||
redirectTo,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// return a successful response
|
||||
return new Response(null, { status: 200 });
|
||||
} catch (error) {
|
||||
const service = await getServerMonitoringService();
|
||||
|
||||
await service.ready();
|
||||
await service.captureException(error as Error);
|
||||
|
||||
// return an error response
|
||||
return new Response(null, { status: 500 });
|
||||
}
|
||||
},
|
||||
{
|
||||
auth: false,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
#### Adding the Trigger to the Database
|
||||
|
||||
We need to add a trigger to the `waitlist` table to listen for updates and send a webhook to the app when a user is approved.
|
||||
|
||||
During development, you can simply add the webhook to your seed file `apps/web/supabase/seed.sql`:
|
||||
|
||||
```sql
|
||||
create trigger "waitlist_approved_update" after update
|
||||
on "public"."waitlist"
|
||||
for each row
|
||||
when (new.approved = true)
|
||||
execute function "supabase_functions"."http_request"(
|
||||
'http://host.docker.internal:3000/api/db/webhook',
|
||||
'POST',
|
||||
'{"Content-Type":"application/json", "X-Supabase-Event-Signature":"WEBHOOKSECRET"}',
|
||||
'{}',
|
||||
'5000'
|
||||
);
|
||||
```
|
||||
|
||||
The above creates a trigger that listens for updates to the `waitlist` table and sends a POST request to the webhook route.
|
||||
|
||||
**Note**: You need to add this trigger to your production database as well. You will replace your `WEBHOOKSECRET` with the secret you set in your `.env` file and the `host.docker.internal:3000` with your production URL.
|
||||
Just like you did for the other existing triggers.
|
||||
|
||||
#### Approving users
|
||||
|
||||
Simply update the `approved` column in the `waitlist` table to `true` to approve a user. You can do so from the Supabase dashboard or by running a query.
|
||||
|
||||
Alternatively, run an update based on the created_at timestamp:
|
||||
|
||||
```sql
|
||||
update public.waitlist
|
||||
set approved = true
|
||||
where created_at < '2024-07-01';
|
||||
```
|
||||
|
||||
#### Email Templates and URL Configuration
|
||||
|
||||
Please make sure to [edit the email template](https://makerkit.dev/docs/next-supabase-turbo/authentication-emails) in your Supabase account.
|
||||
The default email in Supabase does not support PKCE and therefore does not work. By updating it - we replace the existing strategy with the token-based strategy - which the `confirm` route in Makerkit can support.
|
||||
|
||||
Additionally, [please add the following URL to your Supabase Redirect URLS allow list](https://supabase.com/docs/guides/auth/redirect-urls):
|
||||
|
||||
```
|
||||
<your-url>/password-reset
|
||||
```
|
||||
|
||||
This will allow Supabase to redirect users to your app to set their password after they click the email link.
|
||||
|
||||
If you don't do this - the email links will not work.
|
||||
|
||||
#### Disable oAuth
|
||||
|
||||
If you are using any oAuth providers, please disable them in the [Makerkit Auth configuration](../configuration/authentication-configuration#third-party-providers). Since sign-ups are disabled, users will hit errors.
|
||||
Reference in New Issue
Block a user