### 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 (
);
}
```
--------------------------------
### 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.