Default starter kit database setup:
• PostgreSQL database
• Managed by Docker
• Prisma ORM
The directory includes a docker-compose.yml file. To set up your PostgreSQL database locally, run the following command:
docker-compose up
To perform the initial migration:
- Run
yarn migrate:dev
(or use your preferred package manager). - You will be prompted to name your migration. Press Enter to use the default name or provide a custom name.
This configuration can be swapped out at any time.
Run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
The starter kit includes shadcn. My favorite library ever. It uses tailwind under the hood so you can just use tailwind. We've installed a few of the base components such as input
, button
, select
, toast
, and form
.
React Hook Form is installed to manage forms with Zod for validation. There are a couple example components installed such as controlled-input
and controlled-select
export const ControlledInput = ({
name,
label,
placeholder,
type,
min = 0,
}: Props) => {
const { control } = useFormContext();
return (
<FormField
control={control}
name={name}
render={({ field }) => {
return (
<FormItem>
<FormLabel htmlFor={name}>{label}</FormLabel>
<FormControl>
<Input
placeholder={placeholder}
type={type}
min={min}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
);
}}
/>
);
};
Example Usage
const schema = z.object({
firstName: z.string().min(0, formMessages.invalid)
})
type FormValues = z.infer<typeof schema>;
const FormComponent = () => {
const form = useForm<FormValues>({
resolver: zodResolver(schema),
});
return (
<Form {...form}>
<form>
<ControlledInput
name="firstName"
label="First Name"
placeholder="Alejandro Roman"
/>
</form>
</Form>
)
}
The starter kit uses Clerk by default. Follow these steps to set up authentication:
-
Create an account with Clerk and obtain the following keys:
• Secret Key
• Publishable Key
-
Set up webhooks in the Clerk dashboard to register users in your own database, storing a reference.
• Not mandatory, but recommended.
• Logic for handling user creation after sign-up is included in api/auth/webhook. This allows you to store the user’s email and Clerk sub (reference ID in Clerk) for easier management.
• Add the webhook secret to your .env file as CLERK_WEBHOOK_SECRET.
-
(Optional) Add a forced redirect URL after user sign-up in the sign-up page.
• Set the path in the
NEXT_PUBLIC_CLERK_SIGN_UP_FORCE_REDIRECT_URL
variable in your.env
file.
- Create a Posthog account if you haven't.
- Add the following code to layout.tsx to enable PostHog:
Add the following code to layout.tsx
in order to enable posthog
export const PHPageView = dynamic(() => import("./posthog/page-viewer")); 👈 Add this
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<ClerkProvider>
<CSPostHogProvider> 👈 Add this
<html lang="en">
<body className={inter.className}>
<PHPageView /> 👈 Add this
{children}
<Toaster />
</body>
</html>
</CSPostHogProvider> 👈 Add this
</ClerkProvider>
);
}
-
Create a Loops Account
• Sign up for an account on Loops.
• Once your account is set up, navigate to the dashboard to obtain your API keys.
-
Add your keys to the
.env
file
The starter kit includes a method to create contacts on Loops once a user has signed up.
export const sendSignUpEvent = async (user: User) => {
try {
await loops.sendEvent({
email: user.email,
userId: user.id,
eventName: "signup",
});
} catch (error) {
console.error(
`Error sending sign up event to loops:\n-Email: ${user.email}\n-ID: ${user.id}`,
error
);
throw new Error("Error sending sign up event to loops");
}
};
It also includes a very simple method to send transactional emails that I use everytime:
export const sendTransactionalEmail = ({
email,
transactionalId,
dataVariables,
}: TransactionalEmailInputInterface) => {
return loops.sendTransactionalEmail(transactionalId, email, dataVariables);
};
This starter kit includes a boilerplate for integrating Stripe for payment processing, subscription management, and billing portal functionality.
Prerequisites
-
Stripe Account: Create an account on Stripe if you don’t have one.
-
Stripe API Keys: Obtain your Stripe Secret Key and Publishable Key from the Stripe Dashboard.
Environment Variables
Add the following environment variables to your .env
file:
NEXT_PUBLIC_STRIPE_SECRET_KEY=your_stripe_secret_key
NEXT_PUBLIC_BASE_URL=your_base_url
Usage
- Get Stripe Customer: This function checks if a user already has a Stripe customer account by querying their email. If not found, it throws an error.
const stripeCustomer = await getStripeCustomer({ clerkSub });
- Create Checkout Session: This function creates a Stripe checkout session for a subscription. It retrieves or creates a Stripe customer, sets up the checkout session, and returns the session URL.
const sessionUrl = await createCheckoutSession({
clerkSub,
priceId,
successUrl,
cancelUrl,
});
- Create Billing Portal Session: This function creates a billing portal session for the user, allowing them to manage their subscription and payment methods.
const billingPortalUrl = await createBillingPortalSession({ clerkSub });
Make sure to customize the functions as needed and handle errors appropriately in your application.