### Install Project Dependencies with pnpm Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/quick-setup.md This command installs all necessary project dependencies using the pnpm package manager. ```Shell pnpm ``` -------------------------------- ### Launch Supabase Locally with pnpm Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/quick-setup.md This command starts the Supabase services locally. Ensure Docker is installed and running on your system before executing this command. ```Shell pnpm supabase start ``` -------------------------------- ### Start Next.js Development Server with pnpm Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/quick-setup.md This command launches the Next.js development server, making the application accessible locally, typically at http://localhost:3000. ```Shell pnpm dev ``` -------------------------------- ### Clone NextBase Repository using Git Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/getting-started.md This command is used to clone the NextBase Pro private repository from GitHub to your local machine. It's the essential step to get the project files after gaining access. Always clone to maintain privacy and integrity of your code, as forking is discouraged. ```Bash git clone https://github.com/imbhargav5/nextbase-pro.git ``` -------------------------------- ### Supabase CLI Project Setup Commands Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/supabase-for-production.md This section details the essential command-line interface (CLI) steps for initializing and synchronizing your local project with a remote Supabase instance. It covers installing dependencies, authenticating the CLI, linking your project, and pushing your database schema, ensuring a seamless development and deployment workflow. ```Shell pnpm install pnpm supabase login # Create an access token at https://app.supabase.com/account/tokens # Paste the token when prompted. pnpm supabase link --project-ref {projectRef} # Enter your database password when prompted. pnpm supabase db push ``` -------------------------------- ### Start Supabase Local Development Server Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-supabase-locally.md This command initiates the local Supabase development environment using Docker. It pulls the necessary Docker images and starts all Supabase services, making them accessible via local URLs. The first execution may take longer as it downloads images. ```shell pnpm supabase start ``` -------------------------------- ### Cloning and Updating Nextbase Git Repository Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/first-steps.md Provides a sequence of bash commands to clone the Nextbase repository from GitHub, navigate into its directory, and update it with the latest changes. This is essential for setting up the project locally. ```bash git clone https://github.com/imbhargav5/nextbase-ultimate.git ``` ```bash cd nextbase-ultimate ``` ```bash git pull ``` -------------------------------- ### Start Local Development Server Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/dev-environment.md This shell command initiates the local development server for the project. Upon successful execution, the application will typically be accessible via a web browser at http://localhost:3000. ```Shell pnpm dev ``` -------------------------------- ### GitHub Actions Workflow for Vitest Testing Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/writing-unit-tests.md This GitHub Actions workflow automates running Vitest tests on `push` and `pull_request` events. It checks out the repository code, sets up Node.js, installs project dependencies using `pnpm`, and then executes the unit tests. ```YAML name: Test on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Use Node.js uses: actions/setup-node@v2 with: node-version: 16 - name: Install dependencies run: pnpm install - name: Run tests run: pnpm test ``` -------------------------------- ### Supabase Local Environment Variables Configuration Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-supabase-locally.md This snippet displays the structure of the `.env.local.example` file, which serves as a template for defining crucial environment variables for local Supabase development. It includes settings for Supabase URLs and keys, Stripe, email, and analytics, guiding users on how to set up their local development environment. ```env # supabase # These values never change when supabase is ran locally regardless of project NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321/ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0 SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU SUPABASE_DATABASE_PASSWORD=postgres SUPABASE_JWT_SECRET=super-secret-jwt-token-with-at-least-32-characters-long # SUPABASE_PROJECT_REF=SUPABASE_PROJECT_REF # stripe STRIPE_SECRET_KEY=STRIPE_SECRET_KEY NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY STRIPE_WEBHOOK_SECRET=STRIPE_WEBHOOK_SECRET # host NEXT_PUBLIC_SITE_URL=http://localhost:3000 # email ADMIN_EMAIL=admin@myapp.com RESEND_API_KEY=RESEND_API_KEY # analytics # ultimate and pro NEXT_PUBLIC_POSTHOG_API_KEY=NEXT_PUBLIC_POSTHOG_API_KEY NEXT_PUBLIC_POSTHOG_APP_ID=NEXT_PUBLIC_POSTHOG_APP_ID NEXT_PUBLIC_POSTHOG_HOST=NEXT_PUBLIC_POSTHOG_HOST NEXT_PUBLIC_GA_ID=NEXT_PUBLIC_GA_ID UNKEY_ROOT_KEY=UNKEY_ROOT_KEY UNKEY_API_ID=UNKEY_API_ID ## Supabase providers # this file is only used by supabase configtoml for local development # next.js uses .env.local for local development TWITTER_API_KEY=TWITTER_API_KEY TWITTER_API_SECRET=TWITTER_API_SECRET GOOGLE_CLIENT_ID=GOOGLE_CLIENT_ID GOOGLE_CLIENT_SECRET=GOOGLE_CLIENT_SECRET GITHUB_CLIENT_ID=GITHUB_CLIENT_ID GITHUB_CLIENT_SECRET=GITHUB_CLIENT_SECRET ``` -------------------------------- ### Initialize Stripe Client in TypeScript Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This TypeScript snippet demonstrates how to create a Stripe client instance in `src/utils/stripe.ts`. It imports the `Stripe` class and the secret key from a configuration file, then initializes the client with a specific API version for interacting with the Stripe API. ```typescript import { Stripe } from 'stripe'; import { STRIPE_SECRET_KEY } from '../config'; export const stripe = new Stripe(STRIPE_SECRET_KEY, { apiVersion: '2020-08-27', }); ``` -------------------------------- ### Configure Stripe API Keys in .env Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This snippet shows how to set up your Stripe public and secret API keys in the `.env.local` file. These environment variables are crucial for authenticating requests to the Stripe API within the application. ```dotenv STRIPE_PUBLIC_KEY=your_stripe_public_key STRIPE_SECRET_KEY=your_stripe_secret_key ``` -------------------------------- ### Example Admin Panel Page Component in Next.js Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/creating-application-admin-page.md This snippet shows a basic Next.js page component for an admin panel route. It demonstrates the minimal structure for a page that would be placed under the authenticated admin layout. ```TypeScript export default async function YourPageName() { // Your page content goes here return
// Your JSX goes here
; } ``` -------------------------------- ### Initializing Typed Supabase Client and Fetching Data Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/creating-new-supabase-table.md This TypeScript example demonstrates how to initialize a Supabase client using generated database types and fetch data from a 'todos' table. It highlights how the `Database` type ensures type safety for database queries and the returned data structure, providing auto-completion and compile-time checks for improved developer experience. ```typescript // The Database type is generated from your database schema by supabase. import { Database } from '@/lib/database.types'; import { createClient } from '@supabase/supabase-js'; // A simple wrapper around the Supabase client that uses the service role key // Since Database is passed as a generic, the client will be typed correctly. export const supabaseAdminClient = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY, ); export async function getAllTodos() { const { data, error } = await supabaseAdminClient.from('todos').select('*'); /** * The `data` will be typed as `Database['public']['Tables']['todos']['Row'][]`. * It will have the following shape: * { * id: number; * title: string; * is_completed: boolean; * created_at: string; * }[] */ if (error) { throw error; } return data; } ``` -------------------------------- ### Next.js Protected Page Component Example Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/creating-protected-page.md This simple React component defines the content for a protected page. It demonstrates how to create a basic page that will only be accessible to users who have passed both middleware and layout-based authentication checks. ```TypeScript export default function MyProtectedPage() { return (

My Protected Page

This is a protected page only accessible to authenticated users.

); } ``` -------------------------------- ### Run React Email Development Server Command Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/integrations/resend-and-react-email-integration.md This shell command initiates the React Email development server. By executing `pnpm email-dev`, developers can start a local server to interactively preview and test their email templates, streamlining the email development workflow. ```Bash pnpm email-dev ``` -------------------------------- ### Manage Supabase database migrations with pnpm CLI Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/creating-new-supabase-table.md Provides a set of `pnpm` commands for managing Supabase database migrations. This includes creating new migration files, applying migrations to a local database, resetting the local database, and pushing migrations to a production environment. The example also shows the content of a typical migration SQL file. These commands facilitate version control and tracking of database schema changes. ```Shell pnpm supabase migration new create_todos_table ``` ```PostgreSQL -- This is a migration file (e.g., 20240101000000_create_todos_table.sql) CREATE TABLE todos ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, title TEXT, is_completed BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc'::text, NOW()) NOT NULL ); ``` ```Shell pnpm supabase migration up ``` ```Shell pnpm supabase db reset ``` ```Shell pnpm supabase db push ``` -------------------------------- ### Create Stripe Customer Portal Link in TypeScript Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This asynchronous server action generates a URL for the Stripe customer billing portal. It fetches organization details, ensures a Stripe customer exists for the organization, and then creates a Stripe billing portal session, returning its URL. This allows users to manage their subscriptions and billing information directly through Stripe. ```TypeScript export async function createCustomerPortalLinkAction(organizationId: string) { 'use server'; const user = await serverGetLoggedInUser(); const supabaseClient = createSupabaseUserServerActionClient(); const { data, error } = await supabaseClient .from('organizations') .select('id, title') .eq('id', organizationId) .single(); if (error) { throw error; } if (!data) { throw new Error('Organization not found'); } const customer = await createOrRetrieveCustomer({ organizationId: organizationId, organizationTitle: data.title, email: user.email || '', }); if (!customer) throw Error('Could not get customer'); const { url } = await stripe.billingPortal.sessions.create({ customer, return_url: toSiteURL(`/organization/${organizationId}/settings/billing`), }); return url; } ``` -------------------------------- ### Vitest Test Case for Helper Function Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/writing-unit-tests.md An example of a unit test written in Vitest for a helper function `toDateTime`. It demonstrates how to import `expect` and `test` from Vitest, and assert that the `toDateTime` function returns a `Date` object. ```TypeScript import { expect, test } from 'vitest'; import { toDateTime } from './helpers'; test('helpers: toDateTime should return a date object', () => { const date = new Date(); const dateObject = toDateTime(date.getTime()); expect(dateObject).toBeInstanceOf(Date); }); ``` -------------------------------- ### Client-Side Integration of Social Provider Login Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/authentication/login-with-social-providers.md This client-side example demonstrates how to call the `signInWithProvider` server action from a React component. It utilizes a `useToastMutation` hook to manage loading states, success messages, and error handling during the authentication request, and renders a `RenderProviders` component for UI. ```TypeScript const providerMutation = useToastMutation( async (provider: AuthProvider) => { return signInWithProvider(provider, next); }, { loadingMessage: 'Requesting login...', successMessage: 'Redirecting...', errorMessage: 'Failed to login', }, ); // In your component JSX ; ``` -------------------------------- ### Resend Email Sending API Reference Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/integrations/resend-and-react-email-integration.md Comprehensive documentation for the Resend email sending API, specifically detailing the `emails.send` method. It outlines the required parameters, their types, and an example of how to invoke the method for sending emails. ```APIDOC Resend.emails.send(options: EmailOptions): Promise - Description: Sends an email using the Resend service. - Parameters: - options (object): An object containing email details. - to (string): The recipient's email address. - from (string): The sender's email address. - subject (string): The subject line of the email. - html (string | React.ReactElement): The HTML content of the email. Can be a plain HTML string or a React Email component. - Returns: A Promise that resolves upon successful email delivery. - Usage Example (from code): resend.emails.send({ to: 'recipient@example.com', from: 'sender@example.com', subject: 'Invitation to Join', html: , }); - Error Handling: Errors during sending are caught and can be logged or tracked. ``` -------------------------------- ### Streaming Rendering with Server Components and Suspense in Next.js Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/asynchronous-data-fetching.md This Next.js server component demonstrates how to leverage streaming rendering and parallel data fetching using async server components wrapped in Suspense. The BlogListPage fetches blog posts and tags concurrently, rendering parts of the page as data becomes available, significantly improving perceived performance and user experience. It utilizes anonGetAllBlogTags and anonGetPublishedBlogPosts for data retrieval. ```tsx import { T } from '@/components/ui/Typography'; import { PublicBlogList } from '../PublicBlogList'; import { TagsNav } from '../TagsNav'; import { Suspense } from 'react'; import { anonGetAllBlogTags, anonGetPublishedBlogPosts, } from '@/data/anon/internalBlog'; export const metadata = { title: 'Blog List | Nextbase', description: 'Collection of the latest blog posts from the team at Nextbase', icons: { icon: '/images/logo-black-main.ico', }, }; async function Tags() { const tags = await anonGetAllBlogTags(); return ; } async function BlogList() { const blogPosts = await anonGetPublishedBlogPosts(); return ; } export default async function BlogListPage() { return (
Blog All blog posts Here is a collection of the latest blog posts from the team at Nextbase.
Loading tags...}>
Loading posts...}>
); } ``` -------------------------------- ### Create Stripe Checkout Session for Subscriptions in TypeScript Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This asynchronous server action initiates a Stripe checkout session for a new subscription. It supports both standard and trial subscriptions, retrieving necessary user and organization data to create or retrieve a Stripe customer. The function configures the checkout session with payment methods, line items, and success/cancel URLs, returning the session ID for redirection. ```TypeScript export async function createCheckoutSessionAction({ organizationId, priceId, isTrial = false, }: { organizationId: string; priceId: string; isTrial?: boolean; }) { 'use server'; const TRIAL_DAYS = 14; const user = await serverGetLoggedInUser(); const organizationTitle = await getOrganizationTitle(organizationId); const customer = await createOrRetrieveCustomer({ organizationId: organizationId, organizationTitle: organizationTitle, email: user.email || '', }); if (!customer) throw Error('Could not get customer'); if (isTrial) { const stripeSession = await stripe.checkout.sessions.create({ payment_method_types: ['card'], billing_address_collection: 'required', customer, line_items: [ { price: priceId, quantity: 1, }, ], mode: 'subscription', allow_promotion_codes: true, subscription_data: { trial_period_days: TRIAL_DAYS, trial_settings: { end_behavior: { missing_payment_method: 'cancel', }, }, metadata: {}, }, success_url: toSiteURL( `/organization/${organizationId}/settings/billing`, ), cancel_url: toSiteURL(`/organization/${organizationId}/settings/billing`), }); return stripeSession.id; } else { const stripeSession = await stripe.checkout.sessions.create({ payment_method_types: ['card'], billing_address_collection: 'required', customer, line_items: [ { price: priceId, quantity: 1, }, ], mode: 'subscription', allow_promotion_codes: true, subscription_data: { trial_settings: { end_behavior: { missing_payment_method: 'cancel', }, }, }, metadata: {}, success_url: toSiteURL( `/organization/${organizationId}/settings/billing`, ), cancel_url: toSiteURL(`/organization/${organizationId}/settings/billing`), }); return stripeSession.id; } } ``` -------------------------------- ### Asynchronous Data Fetching in Next.js Server Components Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/performance/strategies-for-pages.md This example demonstrates how to perform asynchronous data fetching directly within a Next.js server component. The `PlannedCards` function awaits data from `anonGetPlannedRoadmapFeedbackList` before rendering a list of roadmap feedback cards, leveraging server CPU for efficient data retrieval. ```TypeScript async function PlannedCards() { const plannedCards = await anonGetPlannedRoadmapFeedbackList(); return (
{plannedCards.length ? ( plannedCards.map((card) => ( )) ) : ( Empty )}
); } ``` -------------------------------- ### Next.js Server Component for Dynamic Blog Post Page Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/asynchronous-data-fetching.md This Next.js server component demonstrates asynchronous data fetching for a dynamic blog post page. It uses `generateStaticParams` to pre-render paths, `generateMetadata` to set SEO properties based on fetched data, and the default export `BlogPostPage` to fetch and display blog post content using `anonGetPublishedBlogPostBySlug`. ```tsx import { anonGetPublishedBlogPostBySlug, anonGetPublishedBlogPosts, } from '@/data/anon/internalBlog'; import { Metadata } from 'next'; import { notFound } from 'next/navigation'; import { z } from 'zod'; const paramsSchema = z.object({ slug: z.string(), }); // Return a list of `params` to populate the [slug] dynamic segment export async function generateStaticParams() { const posts = await anonGetPublishedBlogPosts(); return posts.map((post) => ({ slug: post.slug, })); } export async function generateMetadata({ params, }: { params: unknown; }): Promise { // read route params const { slug } = paramsSchema.parse(params); const post = await anonGetPublishedBlogPostBySlug(slug); return { title: `${post.title} | Blog | Nextbase Boilerplate`, description: post.summary, openGraph: { title: `${post.title} | Blog | Nextbase Boilerplate`, description: post.summary, type: 'website', images: post.cover_image ? [post.cover_image] : undefined, }, twitter: { images: post.cover_image ? [post.cover_image] : undefined, title: `${post.title} | Blog | Nextbase Boilerplate`, card: 'summary_large_image', site: '@usenextbase', description: post.summary, }, }; } export default async function BlogPostPage({ params }: { params: unknown }) { try { const { slug } = paramsSchema.parse(params); const post = await anonGetPublishedBlogPostBySlug(slug); return (
{post.cover_image ? ( {post.title} ) : null}

{post.title}

); } catch (error) { return notFound(); } } ``` -------------------------------- ### Example of Sending React Email Component via Resend Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/integrations/resend-and-react-email-integration.md This snippet demonstrates how to programmatically send the `InvitationToJoin` React email component using the Resend API. It shows the `resend.emails.send` method call, passing the React component directly as the `html` content. ```typescript import { resend } from '../utils/email'; import InvitationToJoin from '../emails/InvitationToJoin'; // Other logic... // Send organization invitation email resend.emails.send({ to: 'recipient@example.com', from: 'sender@example.com', subject: 'Invitation to Join', html: ( ), }); ``` -------------------------------- ### Next.js Page Component Utilizing Suspense for Streaming Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/performance/streaming-suspense-rendering.md This Next.js page component, `BlogListPage`, showcases the integration of React's Suspense to wrap server components (`Tags` and `BlogList`). This setup enables streaming server rendering, providing immediate visual feedback to users with fallback content while the actual data is being fetched and rendered. ```JavaScript export default async function BlogListPage() { return (
Blog All blog posts Here is a collection of the latest blog posts from the team at Nextbase.
Loading tags...}>
Loading posts...}>
); } ``` -------------------------------- ### Client-side Usage of Magic Link Authentication Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/authentication/login-with-magic-link.md This client-side example demonstrates how to integrate the magic link authentication into a React component. It uses a useToastMutation hook to manage the asynchronous operation, providing loading, success, and error messages to the user interface. It also handles state updates for success messages. ```TypeScript const magicLinkMutation = useToastMutation( async (email: string) => { return await signInWithMagicLink(email, next); }, { loadingMessage: 'Sending magic link...', errorMessage: 'Failed to send magic link', successMessage: 'Magic link sent!', onSuccess: () => { setSuccessMessage('A magic link has been sent to your email!'); }, onError: (error) => { console.log(error); }, onMutate: () => { setSuccessMessage(null); } } ); // In your component JSX ; ``` -------------------------------- ### Client-Side Data Fetching with React Query in Next.js Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/asynchronous-data-fetching.md This client component (LoginCTAButton) illustrates how to perform client-side data fetching using @tanstack/react-query's useQuery hook. It fetches the user's login status from Supabase (supabaseUserClientComponentClient.auth.getUser()) and manages loading states, suitable for interactive UI elements that require dynamic data. ```tsx 'use client'; import { supabaseUserClientComponentClient } from '@/supabase-clients/user/supabaseUserClientComponentClient'; import { useQuery } from '@tanstack/react-query'; export function LoginCTAButton() { const { data: isLoggedIn, isFetching } = useQuery( ['isLoggedInHome'], async () => { const response = await supabaseUserClientComponentClient.auth.getUser(); return Boolean(response.data.user?.id); }, { // options }, ); // if logged in , show dashboard button else show login button // ... } ``` -------------------------------- ### Next.js Organization Billing Page Component Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This Next.js `async` page component handles the display and management of organization subscription details. It parses the `organizationId` from route parameters using Zod, fetches normalized subscription data and the logged-in user's organization role, and then renders the `OrganizationSubscripionDetails` component. It uses React Suspense for loading states. ```TypeScript import { z } from 'zod'; import { OrganizationSubscripionDetails } from './OrganizationSubscripionDetails'; import { getLoggedInUserOrganizationRole, getNormalizedOrganizationSubscription, } from '@/data/user/organizations'; import { Suspense } from 'react'; import { T } from '@/components/ui/Typography'; const paramsSchema = z.object({ organizationId: z.string(), }); async function Subscription({ organizationId }: { organizationId: string }) { const normalizedSubscription = await getNormalizedOrganizationSubscription(organizationId); const organizationRole = await getLoggedInUserOrganizationRole(organizationId); return ( ); } export default async function OrganizationSettingsPage({ params, }: { params: unknown; }) { const { organizationId } = paramsSchema.parse(params); return ( Loading billing details...}> ; ); } ``` -------------------------------- ### Next.js API Route for Stripe Webhook Event Handling Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This TypeScript code defines a Next.js API route (`/api/stripe/webhook`) that acts as a Stripe webhook endpoint. It securely receives, verifies, and processes incoming Stripe events such as product, price, and subscription changes. The handler buffers the raw request body, constructs the Stripe event, and dispatches updates to a Supabase database based on the event type, ensuring data synchronization with Stripe. ```TypeScript import { errors } from '@/utils/errors'; import { stripe } from '@/utils/stripe'; import { manageSubscriptionStatusChange, upsertPriceRecord, upsertProductRecord, } from '@/utils/supabase-admin'; import { NextApiRequest, NextApiResponse } from 'next'; import { Readable } from 'node:stream'; import Stripe from 'stripe'; // Stripe requires the raw body to construct the event. export const config = { api: { bodyParser: false, }, }; async function buffer(readable: Readable) { const chunks: Array = []; for await (const chunk of readable) { chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk); } return Buffer.concat(chunks); } const relevantEvents = new Set([ 'product.created', 'product.updated', 'price.created', 'price.updated', 'checkout.session.completed', 'customer.subscription.created', 'customer.subscription.updated', 'customer.subscription.deleted', ]); /** * Webhook handler which receives Stripe events and updates the database. * Events handled are product.created, product.updated, price.created, price.updated, * checkout.session.completed, customer.subscription.created, customer.subscription.updated. * * IMPORTANT! Make sure that when your webshite is deployed, the webhook secret is set in the environment variables and * that the webhook is set up in the Stripe dashboard. */ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => { if (req.method === 'POST') { const buf = await buffer(req); const sig = req.headers['stripe-signature']; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET_LIVE ?? process.env.STRIPE_WEBHOOK_SECRET; let event: Stripe.Event; try { if (!sig || !webhookSecret) return; event = stripe.webhooks.constructEvent(buf, sig, webhookSecret); } catch (error: unknown) { errors.add(error); if (error instanceof Error) { return res.status(400).send(`Webhook error: ${error.message}`); } return res.status(400).send(`Webhook Error: ${String(error)}`); } if (relevantEvents.has(event.type)) { try { switch (event.type) { case 'product.created': case 'product.updated': await upsertProductRecord(event.data.object as Stripe.Product); break; case 'price.created': case 'price.updated': await upsertPriceRecord(event.data.object as Stripe.Price); break; case 'customer.subscription.created': case 'customer.subscription.updated': case 'customer.subscription.deleted': { const subscription = event.data.object as Stripe.Subscription; await manageSubscriptionStatusChange( subscription.id, subscription.customer as string, event.type === 'customer.subscription.created', ); break; } case 'checkout.session.completed': { const checkoutSession = event.data .object as Stripe.Checkout.Session; if (checkoutSession.mode === 'subscription') { const subscriptionId = checkoutSession.subscription; await manageSubscriptionStatusChange( subscriptionId as string, checkoutSession.customer as string, true, ); } break; } default: throw new Error('Unhandled relevant event!'); } } catch (error) { errors.add(error); return res .status(400) .send('Webhook error: "Webhook handler failed. View logs."'); } } res.json({ received: true }); } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method Not Allowed'); } }; export default webhookHandler; ``` -------------------------------- ### Trigger Stripe Product and Price Creation Events Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-stripe.md Simulates the creation of product and price events using the Stripe CLI, useful for testing webhook handlers during local development without actual Stripe API calls. ```Shell stripe trigger product.created stripe trigger price.created ``` -------------------------------- ### Stripe CLI Login Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-stripe.md Logs into your Stripe account via the command-line interface, prompting for browser authentication. ```Shell stripe login ``` -------------------------------- ### Supabase Local Development Service Endpoints and Credentials Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-supabase-locally.md This APIDOC entry provides a comprehensive overview of the URLs and authentication keys for interacting with the locally running Supabase instance. It includes endpoints for the API, GraphQL, Database, Supabase Studio, and Inbucket, along with the JWT secret, anonymous key, and service role key necessary for secure access and development. ```APIDOC API URL: http://localhost:54321 GraphQL URL: http://localhost:54321/graphql/v1 DB URL: postgresql://postgres:postgres@localhost:54322/postgres Studio URL: http://localhost:54323 Inbucket URL: http://localhost:54324 JWT secret: super-secret-jwt-token-with-at-least-32-characters-long anon key: anon-key-for-local-development service_role key: service-role-key-for-local-development ``` -------------------------------- ### Forward Stripe Webhooks to Localhost Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-stripe.md Forwards Stripe webhook events to a specified local endpoint, essential for local development and testing of webhook handlers. ```Shell stripe listen --forward-to localhost:3000/api/stripe/webhooks ``` -------------------------------- ### Supabase Production Environment Variables Configuration Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/supabase-for-production.md This snippet presents the structure and key variables for the .env.local file, crucial for configuring a Supabase-backed application in a production setting. It includes placeholders for Supabase API keys, database credentials, JWT secret, and integration with email services like Sendgrid/Postmark, along with the public site URL. ```dotenv # supabase NEXT_PUBLIC_SUPABASE_URL=NEXT_PUBLIC_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY SUPABASE_SERVICE_ROLE_KEY=YOUR_SUPABASE_SERVICE_ROLE_KEY SUPABASE_DATABASE_PASSWORD=postgres SUPABASE_JWT_SECRET=SUPABASE_JWT_SECRET SUPABASE_PROJECT_REF=SUPABASE_PROJECT_REF ``` -------------------------------- ### Default Environment Variables for Supabase Stripe Starter Kit Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/dev-environment.md This snippet provides the default environment variables found in the .env.local.example file. These variables are crucial for configuring Supabase, Stripe, and other services for local development, including database credentials, API keys, and site URLs. ```dotenv # supabase # These values never change when supabase is ran locally regardless of project NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321/ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0 SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU SUPABASE_DATABASE_PASSWORD=postgres SUPABASE_JWT_SECRET=super-secret-jwt-token-with-at-least-32-characters-long # SUPABASE_PROJECT_REF=SUPABASE_PROJECT_REF # stripe STRIPE_SECRET_KEY=STRIPE_SECRET_KEY NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY STRIPE_WEBHOOK_SECRET=STRIPE_WEBHOOK_SECRET # host NEXT_PUBLIC_SITE_URL=http://localhost:3000 # email ADMIN_EMAIL=admin@myapp.com RESEND_API_KEY=RESEND_API_KEY # analytics # ultimate and pro NEXT_PUBLIC_POSTHOG_API_KEY=NEXT_PUBLIC_POSTHOG_API_KEY NEXT_PUBLIC_POSTHOG_APP_ID=NEXT_PUBLIC_POSTHOG_APP_ID NEXT_PUBLIC_POSTHOG_HOST=NEXT_PUBLIC_POSTHOG_HOST NEXT_PUBLIC_GA_ID=NEXT_PUBLIC_GA_ID UNKEY_ROOT_KEY=UNKEY_ROOT_KEY UNKEY_API_ID=UNKEY_API_ID ## Supabase providers # this file is only used by supabase configtoml for local development # next.js uses .env.local for local development TWITTER_API_KEY=TWITTER_API_KEY TWITTER_API_SECRET=TWITTER_API_SECRET GOOGLE_CLIENT_ID=GOOGLE_CLIENT_ID GOOGLE_CLIENT_SECRET=GOOGLE_CLIENT_SECRET GITHUB_CLIENT_ID=GITHUB_CLIENT_ID GITHUB_CLIENT_SECRET=GITHUB_CLIENT_SECRET ``` -------------------------------- ### CSS to Hide Scrollbars for Radix UI Viewports Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/stripe-subscriptions.md This CSS rule targets elements with the `data-radix-scroll-area-viewport` attribute to hide their scrollbars across different browsers. It uses `scrollbar-width: none` for Firefox, `-ms-overflow-style: none` for IE/Edge, and `::-webkit-scrollbar { display: none }` for WebKit browsers (Chrome, Safari). ```CSS [data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none} ``` -------------------------------- ### Supabase Authentication URL Configuration Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/supabase-for-production.md This API documentation outlines the critical URL settings within the Supabase Authentication panel. It specifies how to configure both the primary Site URL and the allowed Redirect URLs, essential for managing user authentication flows securely across local development and production deployments. ```APIDOC Authentication URL Configuration: Site URL: - Purpose: The base URL for your application, used by Supabase for redirects and callbacks. - Values: - http://localhost:3000 (for local development) - https://myapp.com (for production domain) Redirect URLs: - Purpose: A list of URLs that Supabase is permitted to redirect users to after authentication events (e.g., sign-in, password reset). - Values: - http://localhost:3000/auth/callback (specific local callback path) - http://localhost:3000/** (wildcard for all local routes under the domain) - https://myapp.com/auth/callback (specific production callback path) - https://myapp.com/** (wildcard for all production routes under the domain) ``` -------------------------------- ### Vitest Configuration File Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/writing-unit-tests.md This snippet shows the basic configuration for Vitest in `vitest.config.ts`, including the React plugin, JSDOM environment for browser-like testing, and path aliases for the `@` symbol to resolve module imports. ```TypeScript import { defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; import path from 'path'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], test: { environment: 'jsdom', }, // path alias resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, }); ``` -------------------------------- ### Validate API Key in Next.js API Route Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/authentication/login-with-api-key.md This example demonstrates how to validate an API key within a Next.js API route using the @unkey/api library. It checks for the presence of an 'x-api-key' header, verifies the key's validity, and returns appropriate HTTP status codes based on the validation result. ```TypeScript import { NextApiRequest, NextApiResponse } from 'next'; import { verifyKey } from '@unkey/api'; export default async function handler( req: NextApiRequest, res: NextApiResponse, ) { const apiKey = req.headers['x-api-key'] as string; if (!apiKey) { return res.status(401).json({ error: 'API key is required' }); } const { result, error } = await verifyKey(apiKey); if (error || !result.valid) { return res.status(401).json({ error: 'Invalid API key' }); } // API key is valid, proceed with the request // ... res.status(200).json({ message: 'Authenticated successfully' }); } ``` -------------------------------- ### Stripe API Key Environment Variables Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-stripe.md This snippet illustrates the format for storing Stripe's Secret Key and Publishable Key as environment variables. These keys are crucial for authenticating API requests and should be kept secure. ```Environment Variables STRIPE_SECRET_KEY=sk_test_... STRIPE_PUBLISHABLE_KEY=pk_test_51... ``` -------------------------------- ### Command to Run Vitest Unit Tests Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/writing-unit-tests.md This command demonstrates how to execute unit tests using `pnpm` with Vitest. Vitest runs in `NODE_ENV=test` mode and can utilize `.env.test` for environment-specific variables during testing. ```Shell pnpm test:unit ``` -------------------------------- ### Stop Supabase Local Development Server Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/setting-up-supabase-locally.md This command gracefully stops all running Supabase services and Docker containers associated with the local development environment. It is recommended to run this command when local development is not active to free up system resources. ```shell pnpm supabase stop ``` -------------------------------- ### Handle POST Request with Next.js Pages Router API Route Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/guides/mutating-data-with-supabase.md This snippet demonstrates how to create an API route in the Next.js Pages Router (`pages/api`) to handle POST requests. It processes incoming form data and returns a JSON response, also showing how to handle other HTTP methods like GET, PUT, or DELETE by checking `req.method`. ```TypeScript export default function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === 'POST') { // Process a POST request const { name, email } = req.body; res.status(200).json({ name, email }); } else { // Handle any other HTTP method res.status(405).json({ message: 'Method not allowed' }); } } ``` -------------------------------- ### Configure Nextbase Application Environment Variables Source: https://github.com/roubzzz/ultimate-next-base-documentation/blob/main/docs-v3/installation/supabase-for-production.md This snippet provides a list of essential environment variables required for the Nextbase application, covering integrations like Stripe for payments, Resend for email, PostHog and Google Analytics for analytics, and Unkey for API key management. These variables should be set in your .env file. ```dotenv STRIPE_SECRET_KEY=STRIPE_SECRET_KEY NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY STRIPE_WEBHOOK_SECRET=STRIPE_WEBHOOK_SECRET # host NEXT_PUBLIC_SITE_URL=YOUR_DOMAIN_URL # email ADMIN_EMAIL=admin@myapp.com RESEND_API_KEY=RESEND_API_KEY # analytics NEXT_PUBLIC_POSTHOG_API_KEY=NEXT_PUBLIC_POSTHOG_API_KEY NEXT_PUBLIC_POSTHOG_APP_ID=NEXT_PUBLIC_POSTHOG_APP_ID NEXT_PUBLIC_POSTHOG_HOST=NEXT_PUBLIC_POSTHOG_HOST NEXT_PUBLIC_GA_ID=NEXT_PUBLIC_GA_ID UNKEY_ROOT_KEY=UNKEY_ROOT_KEY UNKEY_API_ID=UNKEY_API_ID ```