Skip to content

feat(cli): add RevenueCat payments provider for native frontends#1076

Open
danestves wants to merge 7 commits into
AmanVarshney01:mainfrom
danestves:feat/revenuecat-payments
Open

feat(cli): add RevenueCat payments provider for native frontends#1076
danestves wants to merge 7 commits into
AmanVarshney01:mainfrom
danestves:feat/revenuecat-payments

Conversation

@danestves

@danestves danestves commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What

Adds RevenueCat as a new payments provider for in-app purchases on native (Expo / React Native) apps.

Unlike Polar (web + Better-Auth), RevenueCat is native-gated and auth-agnostic:

  • Offered only when a native frontend (native-bare / native-uniwind / native-unistyles) is selected, with any backend except none.
  • Convex backend → wires the convex-revenuecat component: app.use(revenuecat) in convex.config.ts, webhook via registerRoutes (POST /webhooks/revenuecat), and a revenuecat.ts client exposing hasEntitlement / isSubscriber / getActiveSubscriptions.
  • Other backends → the native react-native-purchases SDK integration only (RevenueCat hosts subscription state).

How it works

  • Schema/prompt/validation: revenuecat added to PaymentsSchema; the prompt offers it when a native frontend is present; validatePaymentsCompatibility errors if selected without a native frontend. Matrix oracle + cases updated (payments-revenuecat-requires-native-frontend).
  • Template handler: restructured so the new native branch and the Convex component are processed without changing Polar's existing behavior. The Convex http.ts webhook is added to the Better-Auth http.ts when present, and a standalone http.ts is generated for Convex + Clerk/none (so the Better-Auth routes are never clobbered).
  • Native scaffolding (all three variants): a shared auth-agnostic RevenueCatProvider + lib/revenue-cat SDK layer, plus styled subscription-status-card and paywall-example components (StyleSheet / NativeWind / unistyles). The provider is mounted via a conditional wrap in each app/_layout.tsx.
  • Env: native .env gets EXPO_PUBLIC_REVENUECAT_IOS_KEY / _ANDROID_KEY / _ENTITLEMENT_ID; Convex .env.local gets REVENUECAT_WEBHOOK_AUTH with setup comments.
  • Web stack-builder: RevenueCat added to apps/web with a native-frontend requirement constraint mirroring how Polar gates on Better-Auth.

Based on 0rtbo/convexpo-revenuecat, adapted to this project's conventions (the reference's user-context coupling and identity auto-sync were intentionally dropped to keep the provider auth-agnostic; example components are SDK/provider-based rather than tied to a specific Convex subscriptions module).

Testing

  • BTS_MATRIX_MODE=smoke matrix: 289 pass / 0 fail (covers revenuecat × all native variants × convex with/without Better-Auth, plus invalid combos rejected with the right rule).
  • Full CLI test suite: 627 pass / 0 fail.
  • CLI typecheck clean; oxlint clean on changed files.
  • Manually rendered convex + better-auth + native-bare and hono + native-uniwind projects and verified the generated provider wrap, Convex wiring, env files, and components.

Notes for maintainers

  • The web builder references r2.better-t-stack.dev/icons/revenuecat.svg — that icon asset still needs to be uploaded to R2 (matching the existing polar.svg convention).
  • convex-revenuecat is pinned to ^0.3.2 (the API the templates are written against).

Summary by CodeRabbit

  • New Features

    • Added RevenueCat as a selectable payments provider.
    • Generated RevenueCat provider integration, paywall UI, and subscription status UI for supported native frontends.
    • Added RevenueCat support for Convex (including webhook route/middleware integration).
    • Included RevenueCat-specific environment variables and setup details during project generation and post-install instructions.
  • Validation / Compatibility

    • RevenueCat is now disabled/invalid unless a compatible native frontend is selected.
    • Updated the CLI and test matrix to include RevenueCat payment scenarios.
  • Chores / Types

    • Extended payment provider enums and template bundles to include RevenueCat.

Adds 'revenuecat' as a payments option, offered only when a native (Expo)
frontend is selected. When the backend is Convex it wires the
convex-revenuecat component (app.use, webhook route, subscription queries);
other backends get the native react-native-purchases SDK integration only.

Native scaffolding (provider, init lib, subscription-status-card and
paywall-example) is generated for all three native variants (bare, uniwind,
unistyles) and is auth-agnostic. Also surfaces RevenueCat in the web
stack-builder with a native-frontend requirement constraint.
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

@danestves is attempting to deploy a commit to the Better T Stack Team on Vercel.

A member of the Team first needs to authorize it.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2996c62c14

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

import { components } from "./_generated/api";

export const revenuecat = new RevenueCat(components.revenuecat, {
REVENUECAT_WEBHOOK_AUTH: process.env.REVENUECAT_WEBHOOK_AUTH ?? "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass through an unset RevenueCat webhook secret

When generating Convex + RevenueCat, .env.local leaves REVENUECAT_WEBHOOK_AUTH unset until the user runs convex env set, but this fallback converts that missing value into "". The convex-revenuecat setup treats secrets shorter than 32 chars as deploy errors, whereas an unset value only rejects webhooks until configured, so fresh projects can fail on the first Convex deploy/dev before the user configures the webhook secret; pass process.env.REVENUECAT_WEBHOOK_AUTH through instead of defaulting to an empty string.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 85c2d9fREVENUECAT_WEBHOOK_AUTH is now passed through as process.env.REVENUECAT_WEBHOOK_AUTH (no ?? ""), matching the reference. When unset it stays undefined, so the component rejects webhooks until it's configured rather than treating "" as an invalid (sub-32-char) secret and failing the Convex deploy.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a2db6055-7453-4f98-a13d-08fe4f77a43d

📥 Commits

Reviewing files that changed from the base of the PR and between b2b916c and d36b138.

📒 Files selected for processing (1)
  • apps/cli/src/helpers/core/post-installation.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cli/src/helpers/core/post-installation.ts

Walkthrough

Adds RevenueCat as a new payments provider option restricted to native (Expo) frontends. Changes include PaymentsSchema enum and dependency versions, CLI prompts and compatibility validation, web UI option constants, test matrix cases and oracle rules, template processor routing and env var generation, Convex backend templates, native layout provider wrapping, RevenueCat SDK utility and context/provider layers, native UI components, UI template integration, post-install instructions, and regenerated template bundle with new RevenueCat templates.

Changes

RevenueCat Payments Integration

Layer / File(s) Summary
PaymentsSchema enum and dependency versions
packages/types/src/schemas.ts, packages/template-generator/src/utils/add-deps.ts
PaymentsSchema and McpServerSchema enums gain "revenuecat"; dependencyVersionMap adds convex-revenuecat@^0.3.2 and react-native-purchases@^9.10.5.
CLI prompt and web compatibility gating
apps/cli/src/prompts/payments.ts, apps/cli/src/utils/compatibility-rules.ts, apps/web/src/app/(home)/new/_components/utils.ts, apps/web/src/lib/constant.ts
getPaymentsChoice parameter renamed from _frontends to frontends and enables revenuecat when a native frontend is detected; validatePaymentsCompatibility enforces revenuecat requires a native frontend; web UI adds hasNativeFrontend helper, extends analyzeStackCompatibility to auto-disable revenuecat, and extends getDisabledReason to block revenuecat without native frontend; TECH_OPTIONS.payments adds the revenuecat entry.
Test matrix cases and oracle rules
apps/cli/test/matrix/cases.ts, apps/cli/test/matrix/oracle.ts
MATRIX_PAYMENTS includes "revenuecat"; createSmokeMatrixCases generates Convex+native-bare and per-native-frontend configs; oracle adds payments-revenuecat-requires-native-frontend MatrixRule, NATIVE_FRONTENDS list, hasNativeFrontend helper, extended validatePayments, and updated classifyMatrixError.
Template processor routing and dependency injection
packages/template-generator/src/template-handlers/payments.ts, packages/template-generator/src/processors/payments-deps.ts
processPaymentsTemplates derives nativeVariant, adds special-case Convex+no-better-auth path, generates native base+variant templates, and short-circuits for Convex backends. processPaymentsDeps adds react-native-purchases to apps/native/package.json and convex-revenuecat to packages/backend/package.json for revenuecat mode.
Environment variable generation
packages/template-generator/src/processors/env-vars.ts
buildNativeVars gains payments parameter and emits EXPO_PUBLIC_REVENUECAT_IOS_KEY, EXPO_PUBLIC_REVENUECAT_ANDROID_KEY, EXPO_PUBLIC_REVENUECAT_ENTITLEMENT_ID; buildConvexBackendVars appends REVENUECAT_WEBHOOK_AUTH; buildConvexCommentBlocks adds RevenueCat webhook setup instructions.
Convex backend templates for RevenueCat
packages/template-generator/templates/payments/revenuecat/convex/..., packages/template-generator/templates/auth/better-auth/convex/backend/convex/http.ts.hbs, packages/template-generator/templates/backend/convex/packages/backend/convex/convex.config.ts.hbs
New revenuecat.ts.hbs instantiates RevenueCat with Convex components and webhook auth, exporting hasEntitlement/isSubscriber/getActiveSubscriptions. New no-better-auth/convex/http.ts.hbs registers RevenueCat routes. Existing http.ts.hbs and convex.config.ts.hbs gain conditional revenuecat import and registration.
Native layout templates: RevenueCatProvider wrapping
packages/template-generator/templates/frontend/native/bare/app/_layout.tsx.hbs, packages/template-generator/templates/frontend/native/unistyles/app/_layout.tsx.hbs, packages/template-generator/templates/frontend/native/uniwind/app/_layout.tsx.hbs
All three native _layout.tsx.hbs variants add conditional RevenueCatProvider import and JSX wrapper around the existing provider tree when payments === "revenuecat".
RevenueCat native SDK utility layer (base)
packages/template-generator/templates/payments/revenuecat/native/base/lib/revenuecat.ts.hbs
New template exports RevenueCatInitResult types, hasProEntitlement, configureRevenueCat with platform/key guards, onCustomerInfoUpdated, refreshProEntitlement, identifyUser/logOutUser/setUserAttributes, offering resolution, getPackages, purchaseAndCheckPro/restoreAndCheckPro/syncAndCheckPro, and isPurchaseCancelledError.
RevenueCatProvider context and hooks (base)
packages/template-generator/templates/payments/revenuecat/native/base/contexts/revenuecat-context.tsx.hbs
New template exports RevenueCatContextValue, useRevenueCat, useIsPro, and RevenueCatProvider component. Provider manages isConfigured/isPro state, gates all operations, handles purchase cancellation, subscribes to customer-info updates, and refreshes entitlement on AppState foreground.
Native paywall and subscription UI components (bare/unistyles/uniwind)
packages/template-generator/templates/payments/revenuecat/native/bare/components/*, packages/template-generator/templates/payments/revenuecat/native/unistyles/components/*, packages/template-generator/templates/payments/revenuecat/native/uniwind/components/*
For each native styling variant, adds PaywallExample component managing package loading, purchase, restore flows with async state and alerts, and SubscriptionStatusCard rendering subscription status with theme-driven styling.
UI template integration: revenuecat components in screens
packages/template-generator/templates/auth/better-auth/native/*/app/(drawer)/index.tsx.hbs, packages/template-generator/templates/frontend/native/*/app/(drawer)/index.tsx.hbs
better-auth and frontend native drawer templates (bare, unistyles, uniwind variants) add conditional imports and rendering of SubscriptionStatusCard and PaywallExample when payments === "revenuecat".
Post-install instructions and MCP server registration
apps/cli/src/helpers/addons/mcp-setup.ts, apps/cli/src/helpers/core/post-installation.ts
mcp-setup adds revenuecat server definition and extends getRecommendedMcpServers to include revenuecat when payments === "revenuecat"; post-installation adds getRevenueCatInstructions helper and integrates RevenueCat setup text into output.
Generated template bundle update
packages/template-generator/src/templates.generated.ts
Adds conditional revenuecat import and registration blocks in payments router, server/app setup, and native layout templates; expands bundle with new payments/revenuecat/... entries; TEMPLATE_COUNT advances from 497 to 507.

Possibly Related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and concisely summarizes the main change: adding RevenueCat as a new payments provider for native frontends, which is the primary objective across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c80508a-7553-4c93-b637-93bdd1a566aa

📥 Commits

Reviewing files that changed from the base of the PR and between cdd244e and 2996c62.

📒 Files selected for processing (27)
  • apps/cli/src/prompts/payments.ts
  • apps/cli/src/utils/compatibility-rules.ts
  • apps/cli/test/matrix/cases.ts
  • apps/cli/test/matrix/oracle.ts
  • apps/web/src/app/(home)/new/_components/utils.ts
  • apps/web/src/lib/constant.ts
  • packages/template-generator/src/processors/env-vars.ts
  • packages/template-generator/src/processors/payments-deps.ts
  • packages/template-generator/src/template-handlers/payments.ts
  • packages/template-generator/src/templates.generated.ts
  • packages/template-generator/src/utils/add-deps.ts
  • packages/template-generator/templates/auth/better-auth/convex/backend/convex/http.ts.hbs
  • packages/template-generator/templates/backend/convex/packages/backend/convex/convex.config.ts.hbs
  • packages/template-generator/templates/frontend/native/bare/app/_layout.tsx.hbs
  • packages/template-generator/templates/frontend/native/unistyles/app/_layout.tsx.hbs
  • packages/template-generator/templates/frontend/native/uniwind/app/_layout.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/convex/backend/convex/revenuecat.ts.hbs
  • packages/template-generator/templates/payments/revenuecat/convex/no-better-auth/convex/http.ts.hbs
  • packages/template-generator/templates/payments/revenuecat/native/bare/components/paywall-example.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/bare/components/subscription-status-card.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/base/lib/revenue-cat/index.ts.hbs
  • packages/template-generator/templates/payments/revenuecat/native/base/providers/RevenueCatProvider.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/unistyles/components/paywall-example.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/unistyles/components/subscription-status-card.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/uniwind/components/paywall-example.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/uniwind/components/subscription-status-card.tsx.hbs
  • packages/types/src/schemas.ts

Comment on lines +479 to +486
{
id: "revenuecat",
name: "RevenueCat",
description: "In-app subscriptions and cross-platform monetization for mobile.",
icon: `${ICON_BASE_URL}/revenuecat.svg`,
color: "from-red-400 to-red-600",
default: false,
},

@coderabbitai coderabbitai Bot Jun 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

URL="https://r2.better-t-stack.dev/icons/revenuecat.svg"
echo "Checking: $URL"
curl -sS -o /dev/null -w "HTTP %{http_code}\n" -I "$URL"

Repository: AmanVarshney01/create-better-t-stack

Length of output: 150


Upload RevenueCat icon asset to R2 before shipping.

The icon asset at https://r2.better-t-stack.dev/icons/revenuecat.svg is missing (HTTP 404). This will render a broken icon in the payments picker UI. Upload the asset to complete this feature.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — revenuecat.svg needs uploading to the R2 icon bucket, which is a maintainer step (I can't push to that bucket). It's called out in the PR description, and the entry follows the existing polar.svg convention, so it resolves once the asset is added.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danestves, understood — thanks for the context. Since the R2 upload is a maintainer step and already documented in the PR description, the implementation-side work is complete. The concern stays open only until the asset is actually uploaded.

Would you like me to open a GitHub issue to track the R2 asset upload (revenuecat.svgr2.better-t-stack.dev/icons/) so it doesn't get missed after this PR merges?

Comment thread packages/template-generator/src/template-handlers/payments.ts
Comment thread packages/template-generator/src/templates.generated.ts
Comment thread packages/template-generator/src/templates.generated.ts Outdated
- Pass REVENUECAT_WEBHOOK_AUTH through unset instead of defaulting to an
  empty string, so an unconfigured secret rejects webhooks rather than
  failing the Convex deploy / accepting unauthenticated requests.
- Normalize EXPO_PUBLIC_REVENUECAT_* platform keys (trim) before the
  presence check so whitespace-only values aren't forwarded to the SDK.
- Add re-entry guards to the example paywalls: purchase and restore are
  now mutually exclusive (isBusy) across bare/uniwind/unistyles.
- lib/revenue-cat/index.ts -> lib/revenuecat.ts (flat, matching lib/constants.ts and lib/use-color-scheme.ts)
- providers/RevenueCatProvider.tsx -> contexts/revenuecat-context.tsx (matching contexts/app-theme-context.tsx); RevenueCatProvider export name kept
- rewire all imports to @/lib/revenuecat and @/contexts/revenuecat-context
Mirror getPolarInstructions: print RevenueCat dashboard + env key + (Convex) webhook setup steps after project creation. Gated on payments=revenuecat (auth-agnostic).
Add the hosted RevenueCat MCP server (https://mcp.revenuecat.ai/mcp) to the MCP server list and recommend it when payments=revenuecat, mirroring the Polar MCP entry.
…nd dashboard

Full parity with how Polar surfaces its example:
- bare components rebuilt with @expo/ui (Host/Column/ExpoUIText/Button)
- uniwind components rebuilt with heroui-native (Card/Button/Spinner)
- unistyles components unchanged (already convention-correct)
- mount SubscriptionStatusCard + PaywallExample on the native dashboard index (app/(drawer)/index.tsx) across all variants and both index sources (frontend/native + auth/better-auth/native), gated on payments=revenuecat only

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9b6d331d-cc49-4b71-95ca-672ca632bf6b

📥 Commits

Reviewing files that changed from the base of the PR and between 12edc47 and b2b916c.

📒 Files selected for processing (14)
  • apps/cli/src/helpers/addons/mcp-setup.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • packages/template-generator/src/templates.generated.ts
  • packages/template-generator/templates/auth/better-auth/native/bare/app/(drawer)/index.tsx.hbs
  • packages/template-generator/templates/auth/better-auth/native/unistyles/app/(drawer)/index.tsx.hbs
  • packages/template-generator/templates/auth/better-auth/native/uniwind/app/(drawer)/index.tsx.hbs
  • packages/template-generator/templates/frontend/native/bare/app/(drawer)/index.tsx.hbs
  • packages/template-generator/templates/frontend/native/unistyles/app/(drawer)/index.tsx.hbs
  • packages/template-generator/templates/frontend/native/uniwind/app/(drawer)/index.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/bare/components/paywall-example.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/bare/components/subscription-status-card.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/uniwind/components/paywall-example.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/uniwind/components/subscription-status-card.tsx.hbs
  • packages/types/src/schemas.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/template-generator/templates/payments/revenuecat/native/uniwind/components/subscription-status-card.tsx.hbs
  • packages/template-generator/templates/payments/revenuecat/native/bare/components/paywall-example.tsx.hbs
  • packages/template-generator/src/templates.generated.ts

Comment thread apps/cli/src/helpers/core/post-installation.ts Outdated
Post-install instructions omitted EXPO_PUBLIC_REVENUECAT_ENTITLEMENT_ID, which env-vars.ts writes to apps/native/.env and the SDK lib reads. Add it so the printed setup matches the generated env contract.
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