### Setup Polar Subscription Client with Clerk Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Initializes the Polar.sh client, integrating it with Clerk for user authentication. It configures the client to fetch user information and specifies product IDs for subscription tiers. ```typescript // convex/subscriptions.ts import { Polar } from "@convex-dev/polar"; import { components } from "./_generated/api"; export const polar = new Polar(components.polar, { getUserInfo: async (ctx) => { const identity = await (ctx as any).auth.getUserIdentity(); if (!identity) { throw new Error("Not authenticated"); } return { userId: identity.subject, // Using Clerk user ID directly email: identity.email || "", }; }, server: "sandbox", // Use "production" for live products: { pro: process.env.POLAR_PRODUCT_PRO_ID || "", }, }); // Export API functions from the Polar client export const { changeCurrentSubscription, cancelCurrentSubscription, getConfiguredProducts, listAllProducts, generateCheckoutLink, generateCustomerPortalUrl, } = polar.api(); ``` -------------------------------- ### Configure Convex HTTP Router for Polar Webhooks Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Configures the Convex HTTP router to handle incoming webhook events from Polar.sh. This setup allows the backend to receive real-time updates on subscription status changes. ```typescript // convex/http.ts import { httpRouter } from "convex/server"; import { polar } from "./subscriptions"; const http = httpRouter(); // This registers POST /polar/events endpoint // Handles subscription.created, subscription.updated, subscription.canceled, etc. polar.registerRoutes(http); export default http; ``` -------------------------------- ### Integrate Polar.sh Component with Convex Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Registers the Polar.sh component with the Convex application. This is achieved by importing the `polar` configuration from `@convex-dev/polar/convex.config.js` and using `app.use(polar)`. ```typescript // convex/convex.config.ts import { defineApp } from "convex/server"; import polar from "@convex-dev/polar/convex.config.js"; const app = defineApp(); app.use(polar); export default app; ``` -------------------------------- ### Set Up Required Environment Variables Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Lists the essential environment variables required for the application to function correctly. These include Convex URL, Clerk publishable and secret keys, Clerk JWT issuer domain, and Polar.sh product IDs. ```bash # .env.local VITE_CONVEX_URL=https://your-project.convex.cloud VITE_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... CLERK_JWT_ISSUER_DOMAIN=https://your-clerk.clerk.accounts.dev VITE_POLAR_PRODUCT_PRO_ID=prod_... POLAR_PRODUCT_PRO_ID=prod_... ``` -------------------------------- ### Use a Convex Query Function in React (TypeScript) Source: https://github.com/devczero/tanstackstart-convex-clerk-polarsh-starter/blob/main/convex/README.md This example illustrates how to consume a Convex query function within a React component using the `useQuery` hook. It shows how to pass arguments to the query and how the returned data can be accessed. ```typescript const data = useQuery(api.myFunctions.myQueryFunction, { first: 10, second: "hello", }); ``` -------------------------------- ### Implement Protected Route Guard with Redirection Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Creates a protected route layout that ensures users are authenticated before accessing specific sections of the application. If a user is not authenticated, they are redirected to the home page. ```typescript // src/routes/_authed.tsx import { createFileRoute, Outlet, redirect } from '@tanstack/react-router' export const Route = createFileRoute('/_authed')({ beforeLoad: ({ context }) => { if (!context.userId) { throw redirect({ to: '/' }) } }, component: () => , }) // All routes under /_authed/ require authentication: // - /_authed/dashboard.tsx // - /_authed/settings.tsx ``` -------------------------------- ### Display Subscription Status Badge with React Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Shows a visual badge indicating the user's subscription status (Pro or Upgrade) in the navigation. It uses the `useSubscription` hook to get the subscription state and `@tanstack/react-router` for navigation. The component is only rendered for signed-in users via `SignedIn` from `@clerk/tanstack-react-start`. ```typescript // src/components/SubscriptionBadge.tsx import { useSubscription } from '~/hooks/useSubscription'; import { SignedIn } from '@clerk/tanstack-react-start'; import { Link } from '@tanstack/react-router'; export function SubscriptionBadge() { return ( ); } function SubscriptionBadgeInner() { const { isPro } = useSubscription(); if (isPro) { return ( Pro ); } return ( Upgrade ); } ``` -------------------------------- ### Set up Root Route with Clerk and Convex Providers Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Configures the application's root route, integrating Clerk for authentication and Convex for backend services. It handles server-side authentication token retrieval for Convex and sets up the necessary provider context for nested routes. ```typescript // src/routes/__root.tsx import { ClerkProvider, useAuth } from '@clerk/tanstack-react-start' import { ConvexProviderWithClerk } from 'convex/react-clerk' import { createServerFn } from '@tanstack/react-start' import { auth } from '@clerk/tanstack-react-start/server' const fetchClerkAuth = createServerFn({ method: 'GET' }).handler(async () => { const { getToken, userId } = await auth() const token = await getToken({ template: 'convex' }) return { userId, token } }) export const Route = createRootRouteWithContext<{ queryClient: QueryClient convexClient: ConvexReactClient convexQueryClient: ConvexQueryClient }>()({ beforeLoad: async (ctx) => { const { userId, token } = await fetchClerkAuth() // Set Clerk auth token for SSR HTTP queries if (token) { ctx.context.convexQueryClient.serverHttpClient?.setAuth(token) } return { userId, token } }, component: () => ( ), }) ``` -------------------------------- ### Use a Convex Mutation Function in React (TypeScript) Source: https://github.com/devczero/tanstackstart-convex-clerk-polarsh-starter/blob/main/convex/README.md This example shows how to use a Convex mutation function within a React component using the `useMutation` hook. It covers both fire-and-forget usage and how to handle the promise returned by the mutation to access its result. ```typescript const mutation = useMutation(api.myFunctions.myMutationFunction); function handleButtonPress() { // fire and forget, the most common way to use mutations mutation({ first: "Hello!", second: "me" }); // OR // use the result once the mutation has completed mutation({ first: "Hello!", second: "me" }).then((result) => console.log(result), ); } ``` -------------------------------- ### Display Customer Portal Link with React Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Renders a link to Polar.sh's customer portal for subscription management. It requires the `@convex-dev/polar/react` package and a `subscription` object as input. The `polarApi` prop is used to configure the generation of the customer portal URL. ```typescript // src/routes/_authed/settings.tsx import { CustomerPortalLink } from '@convex-dev/polar/react'; import { api } from '../../../convex/_generated/api'; function ActiveSubscriptionView({ subscription }: { subscription: any }) { return (

Subscription Status: {subscription.status}

Pro Manage Subscription
); } ``` -------------------------------- ### Query User Subscription Status Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt A server-side Convex query to retrieve the current user's subscription status. It derives `isPro` and `isFree` flags based on the subscription details and returns them along with the subscription object. ```typescript // convex/subscriptions.ts import { query } from "./_generated/server"; export const getMySubscription = query({ args: {}, handler: async (ctx) => { const identity = await ctx.auth.getUserIdentity(); if (!identity) { return null; } const subscription = await polar.getCurrentSubscription(ctx as any, { userId: identity.subject, }); // Derive isPro flag based on product key const isPro = subscription?.productKey === "pro" && subscription?.status === "active"; return { ...subscription, isPro, isFree: !subscription, }; }, }); // Usage result: // { // productKey: "pro", // status: "active", // isPro: true, // isFree: false // } ``` -------------------------------- ### Configure TanStack Router with Convex and React Query Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Sets up the TanStack router, integrating Convex's real-time client and React Query for efficient data management. It initializes Convex clients, configures QueryClient with Convex-specific hashing and query functions, and wraps the router with ConvexProvider. ```typescript // src/router.tsx import { createRouter } from '@tanstack/react-router' import { routerWithQueryClient } from '@tanstack/react-router-with-query' import { ConvexProvider, ConvexReactClient } from 'convex/react' import { ConvexQueryClient } from '@convex-dev/react-query' import { QueryClient } from '@tanstack/react-query' import { routeTree } from './routeTree.gen' export function getRouter() { const CONVEX_URL = (import.meta as any).env.VITE_CONVEX_URL! const convex = new ConvexReactClient(CONVEX_URL, { unsavedChangesWarning: false, }) const convexQueryClient = new ConvexQueryClient(convex) const queryClient: QueryClient = new QueryClient({ defaultOptions: { queries: { queryKeyHashFn: convexQueryClient.hashFn(), queryFn: convexQueryClient.queryFn(), gcTime: 5000, }, }, }) convexQueryClient.connect(queryClient) const router = routerWithQueryClient( createRouter({ routeTree, defaultPreload: 'intent', scrollRestoration: true, defaultPreloadStaleTime: 0, context: { queryClient, convexClient: convex, convexQueryClient }, Wrap: ({ children }) => ( {children} ), }), queryClient, ) return router } ``` -------------------------------- ### Define Convex Database Schema Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Defines the database schema for the application using Convex's type-safe schema builder. It specifies tables and their fields, including an index for efficient lookups. ```typescript // convex/schema.ts import { defineSchema, defineTable } from 'convex/server' import { v } from 'convex/values' export default defineSchema({ posts: defineTable({ id: v.string(), title: v.string(), body: v.string(), }).index('id', ['id']) }) ``` -------------------------------- ### Render Polar.sh Checkout Link for Subscriptions Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Provides a component that renders a checkout button, facilitating redirection to the Polar.sh payment flow for subscription management. It conditionally displays either a 'Subscribe Now' button or a 'Manage Subscription' link based on the user's subscription status. ```typescript // src/routes/pricing.tsx import { CheckoutLink } from '@convex-dev/polar/react'; import { api } from '../../convex/_generated/api'; function ProPlanCard() { const { isPro } = useSubscription(); return (

Pro

$9.99/mo

{isPro ? ( Manage Subscription ) : ( Subscribe Now )}
); } ``` -------------------------------- ### React Hook for Subscription State Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt A client-side React hook (`useSubscription`) that leverages TanStack Query and Convex integration to fetch and manage the user's subscription state. It provides derived boolean flags for easier UI logic. ```typescript // src/hooks/useSubscription.ts import { useSuspenseQuery } from "@tanstack/react-query"; import { convexQuery } from "@convex-dev/react-query"; import { api } from "../../convex/_generated/api"; export function useSubscription() { const { data } = useSuspenseQuery( convexQuery(api.subscriptions.getMySubscription, {}) ); return { subscription: data, isPro: data?.isPro ?? false, isFree: data?.isFree ?? true, isActive: data?.status === "active", }; } // Usage in component: // const { isPro, isFree, isActive, subscription } = useSubscription(); // if (isPro) { /* show premium features */ } ``` -------------------------------- ### Query Authenticated User Profile Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Retrieves the authenticated user's identity information from Clerk using a Convex query. This function is useful for accessing user details like email and name within the application. ```typescript // convex/user.ts import { query } from './_generated/server' export const profile = query({ args: {}, handler: async (ctx) => { return ctx.auth.getUserIdentity() }, }) // Returns Clerk UserIdentity object: // { // subject: "user_2abc123...", // email: "user@example.com", // name: "John Doe", // ... // } ``` -------------------------------- ### Configure Clerk Authentication for Convex Source: https://context7.com/devczero/tanstackstart-convex-clerk-polarsh-starter/llms.txt Sets up Convex to validate JWT tokens issued by Clerk. This configuration requires the `CLERK_JWT_ISSUER_DOMAIN` environment variable to be set. It uses the `AuthConfig` type from `convex/server`. ```typescript // convex/auth.config.ts import type { AuthConfig } from 'convex/server' export default { providers: [ { // Configure with your Clerk JWT Issuer Domain // See https://docs.convex.dev/auth/clerk#configuring-dev-and-prod-instances domain: process.env.CLERK_JWT_ISSUER_DOMAIN!, applicationID: 'convex', }, ], } satisfies AuthConfig ``` -------------------------------- ### Define a Convex Mutation Function (TypeScript) Source: https://github.com/devczero/tanstackstart-convex-clerk-polarsh-starter/blob/main/convex/README.md This snippet demonstrates the definition of a mutation function in Convex using TypeScript. It includes argument validation and shows how to insert data into the database and retrieve the newly created document. Mutations can also perform read operations. ```typescript // convex/myFunctions.ts import { mutation } from "./_generated/server"; import { v } from "convex/values"; export const myMutationFunction = mutation({ // Validators for arguments. args: { first: v.string(), second: v.string(), }, // Function implementation. handler: async (ctx, args) => { // Insert or modify documents in the database here. // Mutations can also read from the database like queries. // See https://docs.convex.dev/database/writing-data. const message = { body: args.first, author: args.second }; const id = await ctx.db.insert("messages", message); // Optionally, return a value from your mutation. return await ctx.db.get("messages", id); }, }); ``` -------------------------------- ### Define a Convex Query Function (TypeScript) Source: https://github.com/devczero/tanstackstart-convex-clerk-polarsh-starter/blob/main/convex/README.md This snippet shows how to define a query function in Convex using TypeScript. It includes argument validation using `convex/values` and demonstrates reading data from the database within the handler. The function takes a number and a string as arguments and returns documents from a specified table. ```typescript // convex/myFunctions.ts import { query } from "./_generated/server"; import { v } from "convex/values"; export const myQueryFunction = query({ // Validators for arguments. args: { first: v.number(), second: v.string(), }, // Function implementation. handler: async (ctx, args) => { // Read the database as many times as you need here. // See https://docs.convex.dev/database/reading-data. const documents = await ctx.db.query("tablename").collect(); // Arguments passed from the client are properties of the args object. console.log(args.first, args.second); // Write arbitrary JavaScript here: filter, aggregate, build derived data, // remove non-public properties, or create new objects. return documents; }, }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.