#How to use Polar with Convex
5 messages · Page 1 of 1 (latest)
Hi @deft fable. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To use Polar with Convex in your Next.js 15 + Convex monorepo (with ConvexAuth), follow these up-to-date steps based on the latest official documentation and community guidance:
1. Install the Polar Component
In your Convex project, install the Polar component:
npm install @convex-dev/polar
Then, register the component in your convex/convex.config.ts:
// convex/convex.config.ts
import { defineApp } from "convex/server";
import polar from "@convex-dev/polar/convex.config";
const app = defineApp();
app.use(polar);
export default app;
Set your Polar organization token:
npx convex env set POLAR_ORGANIZATION_TOKEN <your_token>
2. Initialize the Polar Client
In your Convex backend (e.g., convex/example.ts), initialize the Polar client:
import { Polar } from "@convex-dev/polar";
import { api, components } from "./_generated/api";
export const polar = new Polar(components.polar, {
getUserInfo: async (ctx) => {
const user = await ctx.runQuery(api.example.getCurrentUser);
return {
userId: user._id,
email: user.email,
};
},
products: {
premiumMonthly: "product_id_from_polar",
premiumYearly: "product_id_from_polar",
},
// Optionally set organizationToken, webhookSecret, server, etc.
});
3. Set Up Polar Webhooks
- In the Polar dashboard, create a webhook with your Convex site URL +
/polar/events(e.g.,<https://your-app.convex.site/polar/events>). - Enable the following events:
product.created,product.updated,subscription.created,subscription.updated. - Set the webhook secret in Convex:
npx convex env set POLAR_WEBHOOK_SECRET <your_webhook_secret>
- Register the webhook handler in
convex/http.ts:
import { httpRouter } from "convex/server";
import { polar } from "./example";
const http = httpRouter();
polar.registerRoutes(http as any);
export default http;
4. Sync Existing Products (If Needed)
If you created products in Polar before setting up the Convex integration, you must sync them:
export const syncProducts = action({
args: {},
handler: async (ctx) => {
await polar.syncProducts(ctx);
},
});
5. Add Subscription UI Components
Use the provided React components in your Next.js app:
import { CheckoutLink, CustomerPortalLink } from "@convex-dev/polar/react";
import { api } from "../convex/_generated/api";
// For new subscriptions
<CheckoutLink
polarApi={api.example}
productIds={[products.premiumMonthly.id, products.premiumYearly.id]}
embed={false}
>
Upgrade to Premium
</CheckoutLink>
// For managing existing subscriptions
<CustomerPortalLink
polarApi={{ generateCustomerPortalUrl: api.example.generateCustomerPortalUrl }}
>
Manage Subscription
</CustomerPortalLink>
Add subscription UI components
6. Access Subscription Data
Query subscription info in your Convex backend:
export const getCurrentUser = query({
handler: async (ctx) => {
const user = await ctx.db.query("users").first();
if (!user) throw new Error("No user found");
const subscription = await polar.getCurrentSubscription(ctx, {
userId: user._id,
});
return {
...user,
subscription,
isFree: !subscription,
isPremium:
subscription?.productKey === "premiumMonthly" ||
subscription?.productKey === "premiumYearly",
};
},
});
7. Handle Subscription Changes
You can change or cancel subscriptions using the provided actions:
const changeSubscription = useAction(api.example.changeCurrentSubscription);
await changeSubscription({ productId: "new_product_id" });
const cancelSubscription = useAction(api.example.cancelCurrentSubscription);
await cancelSubscription({ revokeImmediately: true });
Note:
- If you need to backfill products, use the
syncProductsaction as described above. - The Polar component is actively maintained, and recent updates have addressed common issues like backfilling and webhook handling.