Skip to content

Scaffold Polar billing (checkout + webhooks) behind feature flag (Vibe Kanban)#119

Merged
peelar merged 4 commits into
mainfrom
vk/dd80-task-0-3-polar-i
Jan 14, 2026
Merged

Scaffold Polar billing (checkout + webhooks) behind feature flag (Vibe Kanban)#119
peelar merged 4 commits into
mainfrom
vk/dd80-task-0-3-polar-i

Conversation

@peelar

@peelar peelar commented Jan 12, 2026

Copy link
Copy Markdown
Owner

Implements the deferred Task 0.3 (Polar Integration) end-to-end, while keeping every codepath completely hidden behind a static feature flag until brand features are ready.

What changed

  • Added a static enablePolarBillingFlag (billing.enable-polar) that currently always evaluates to false.
  • Added Polar billing API routes:
    • GET /api/billing/me to expose current plan/status to the UI.
    • GET /api/billing/polar/checkout to create a Polar checkout session and redirect.
    • GET /api/billing/polar/portal to create a Polar customer session and redirect to the customer portal.
  • Added a signature-verified Polar webhook handler at POST /api/webhooks/polar to react to subscription.* events.
  • Added a new billing page at /settings/billing (gated by the feature flag).
  • Added an UpgradePrompt UI component (mounted in the Brand panel) that becomes visible only when billing is enabled.
  • Extended user_metadata to store Polar + subscription state and added a Prisma migration.
  • Added Polar setup instructions in docs/development/POLAR_SETUP.md.

Why
This task is intentionally deferred until all brand features are verified via manual tier setting (Task 0.1). Shipping the billing plumbing now (but hidden) reduces future integration risk and makes enabling payments a deliberate, single-flag change when we’re ready.

Implementation details

  • Hard-gated rollout: when the flag is off, the billing UI does not render and the billing/webhook routes return 404.
  • Checkout mapping: checkout creation sets external_customer_id (and metadata) to the app userId, so webhook events can be mapped back to users reliably.
  • Webhook security: webhook requests are signature-verified using @polar-sh/sdk/webhooks (Standard Webhooks headers).
  • Tier + status handling: subscription state is upserted onto user_metadata; past_due is treated as brand (status recorded as past_due), and cancellation/revocation downgrades appropriately.
  • Portal access: customer portal redirection uses Polar customer sessions created via external_customer_id.
  • Config: requires POLAR_ACCESS_TOKEN, POLAR_PRODUCT_ID, and POLAR_WEBHOOK_SECRET (plus optional sandbox settings) — see docs/development/POLAR_SETUP.md.

This PR was written using Vibe Kanban

Summary by CodeRabbit

  • New Features

    • Settings > Billing page to view plan, status, and renewal/cancellation dates.
    • Polar billing integration: checkout flow, customer portal redirect, and webhook-driven subscription updates.
    • Per-user subscription metadata stored (tier, status, cancel flag, current period end, ends at).
    • Feature flag added to gate Polar billing (disabled by default).
  • Documentation

    • Added Polar billing setup guide.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel

vercel Bot commented Jan 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
dopeshot Ready Ready Preview, Comment Jan 14, 2026 8:18am
dopeshot-landing Ready Ready Preview, Comment Jan 14, 2026 8:18am

@changeset-bot

changeset-bot Bot commented Jan 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: baa3dc9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
dopeshot-app Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jan 12, 2026

Copy link
Copy Markdown

Walkthrough

This pull request adds a Polar billing integration scaffold behind a feature flag. Changes include a Prisma migration and schema additions for subscription metadata and Polar IDs, a new dependency (@polar-sh/sdk), server utilities for Polar API interaction, API routes for billing info, Polar checkout, Polar portal, and Polar webhooks, a billing settings page and UI updates, a feature flag billing.enable-polar (disabled by default), setup documentation, and a changeset.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/Browser
    participant App as App (Next.js)
    participant DB as Database

    User->>App: GET /api/billing/me
    App->>App: Check enablePolarBillingFlag
    App->>App: Verify session
    App->>DB: Query user metadata
    DB-->>App: Return billing data (tier, status, dates, IDs)
    App-->>User: Return BillingMeResponse (tier, status, dates)
Loading
sequenceDiagram
    participant User as User/Browser
    participant App as App (Next.js)
    participant PolarAPI as Polar API

    User->>App: GET /api/billing/polar/checkout
    App->>App: Check enablePolarBillingFlag
    App->>App: Verify session & email
    App->>PolarAPI: POST /v1/checkouts (email, product, return URLs, metadata)
    PolarAPI-->>App: Return checkout_url
    App-->>User: 303 Redirect to Polar checkout_url
    User->>PolarAPI: Complete checkout
    PolarAPI-->>User: Redirect to success_url (?checkout=success)
Loading
sequenceDiagram
    participant PolarAPI as Polar API
    participant App as App (Webhook Handler)
    participant DB as Database

    PolarAPI->>App: POST /api/webhooks/polar (subscription event)
    App->>App: Check enablePolarBillingFlag
    App->>App: Verify webhook signature
    App->>App: Validate event type (subscription.*)
    App->>App: Resolve user (external_id, metadata.user_id, or email)
    App->>App: Derive tier & status
    App->>DB: Upsert user metadata (tier, status, cancel flag, dates, polar IDs)
    DB-->>App: Confirm update
    App-->>PolarAPI: Return 202 Accepted
Loading


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Free

📥 Commits

Reviewing files that changed from the base of the PR and between 32049fd and baa3dc9.

📒 Files selected for processing (4)
  • apps/app/src/app/api/billing/me/route.ts
  • apps/app/src/app/api/billing/polar/checkout/route.ts
  • apps/app/src/app/api/billing/polar/portal/route.ts
  • apps/app/src/app/api/webhooks/polar/route.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/app/src/app/api/billing/polar/portal/route.ts
  • apps/app/src/app/api/billing/polar/checkout/route.ts
  • apps/app/src/app/api/webhooks/polar/route.ts

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

@peelar peelar changed the title Task 0.3: Polar Integration (Deferred) (vibe-kanban) Scaffold Polar billing (checkout + webhooks) behind feature flag (Vibe Kanban) Jan 12, 2026
…ehind a static feature flag** (`enablePolarBillingFlag`) that currently always returns `false`.

- Feature flag: `apps/app/src/lib/feature-flags.ts`
- Webhook handler (signature-verified via `@polar-sh/sdk/webhooks`): `apps/app/src/app/api/webhooks/polar/route.ts`
- Checkout + portal redirects: `apps/app/src/app/api/billing/polar/checkout/route.ts`, `apps/app/src/app/api/billing/polar/portal/route.ts`
- Logged-in billing status endpoint (used by UI): `apps/app/src/app/api/billing/me/route.ts`
- Upgrade UI component: `apps/app/src/components/auth/upgrade-prompt.tsx` (also mounted in `apps/app/src/components/brand/brand-panel.tsx`)
- Billing settings page (404s while flag is off): `apps/app/src/app/settings/billing/page.tsx`
- DB fields + migration for subscription state: `apps/app/prisma/schema.prisma`, `apps/app/prisma/migrations/20260112123000_add_polar_billing_fields/migration.sql`
- Polar-side setup doc: `docs/development/POLAR_SETUP.md`
@peelar peelar merged commit ceabd1d into main Jan 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant