← Back to Home

RevenueCat Shipyard 2026

Technical Documentation

Architecture, tech stack, and RevenueCat implementation

Tech Stack

LayerTechnologyPurpose
Mobile FrameworkReact Native + Expo SDK 54Cross-platform iOS/Android
Routingexpo-router (file-based)Navigation and deep linking
BackendConvexReal-time database, server functions, webhooks
AuthenticationClerkEmail, Apple, Google sign-in
SubscriptionsRevenueCatBilling, entitlements, paywall, analytics
AI ExtractionGoogle Gemini 2.0 FlashRecipe parsing from URLs, YouTube, cookbook photos
Voice AssistantSpeechmatics FlowReal-time voice interaction in Cook Mode
MessagingOneSignalIn-app messaging and push notifications
StylingNativeWind v4 (Tailwind CSS)Responsive styling with dark mode
DistributionEAS Build + TestFlightiOS builds with OTA update support

Architecture Overview

┌──────────────────────────────────────────────────────────┐
│                    MOBILE CLIENT                          │
│  React Native + Expo SDK 54                              │
│                                                          │
│  ┌─────────────┐  ┌──────────────┐  ┌────────────────┐  │
│  │ Clerk Auth  │  │ RevenueCat   │  │ OneSignal SDK  │  │
│  │ (identity)  │  │ SDK (billing)│  │ (messaging)    │  │
│  └──────┬──────┘  └──────┬───────┘  └───────┬────────┘  │
│         │                │                   │           │
│  ┌──────┴────────────────┴───────────────────┴────────┐  │
│  │          SubscriptionContext (global state)         │  │
│  │  isPremium, tier, purchase(), restore(), refresh()  │  │
│  └────────────────────────┬───────────────────────────┘  │
│                           │                              │
│  ┌────────────────────────┴───────────────────────────┐  │
│  │              PaywallModal (6 triggers)              │  │
│  │  Recipe limit · Scan limit · AI chat · Exclusive    │  │
│  │  content · Shop discount · Feature gate             │  │
│  └────────────────────────────────────────────────────┘  │
└──────────────────────────┬───────────────────────────────┘
                           │
              Convex React Client (real-time sync)
                           │
┌──────────────────────────┴───────────────────────────────┐
│                    CONVEX BACKEND                         │
│                                                          │
│  ┌──────────────────┐  ┌──────────────────────────────┐  │
│  │ HTTP Router      │  │ Server Functions             │  │
│  │                  │  │                              │  │
│  │ /webhooks/       │  │ Queries:                     │  │
│  │   revenuecat     │  │   getSubscriptionStatus()    │  │
│  │   clerk          │  │   isPremium()                │  │
│  │                  │  │   checkRecipeLimit()         │  │
│  │ HMAC-SHA256      │  │   checkScanLimit()           │  │
│  │ verification     │  │   getCreatorEarnings()       │  │
│  │                  │  │                              │  │
│  │                  │  │ Mutations:                    │  │
│  │                  │  │   syncSubscriptionFromClient()│  │
│  │                  │  │   updateSubscription()        │  │
│  │                  │  │   clearSubscription()         │  │
│  └──────────────────┘  └──────────────────────────────┘  │
│                                                          │
│  ┌──────────────────────────────────────────────────────┐ │
│  │                  Convex Database                     │ │
│  │  users · recipes · revenueTransactions              │ │
│  │  creatorProfiles · creatorPayouts · recipeEngagement│ │
│  └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
   ┌────────────┐  ┌────────────┐  ┌────────────────┐
   │ RevenueCat │  │   Clerk    │  │  OneSignal     │
   │  Cloud     │  │   Cloud    │  │  Cloud         │
   │ (billing)  │  │  (auth)    │  │ (push/IAM)    │
   └────────────┘  └────────────┘  └────────────────┘

RevenueCat Implementation

Products and Entitlements

Product IDPriceTypeEntitlement
digero_plus_monthly$4.99/moAuto-renewableplus
digero_plus_annual$49.99/yrAuto-renewableplus
digero_creator_monthly$9.99/moAuto-renewablecreator
digero_creator_annual$89.99/yrAuto-renewablecreator

Entitlement hierarchy: creator grants all plus features plus creator-specific tools.

Client-Side SDK Integration

Initialization (lib/revenuecat.ts)

  • RevenueCat SDK configured on app launch with Clerk user ID as the app_user_id
  • Enables cross-platform identity mapping between Clerk, RevenueCat, and Convex
  • StoreKit 2 enabled for simulator testing

Subscription Context (contexts/SubscriptionContext.tsx)

  • Global React context wrapping the entire app
  • Listens to CustomerInfo updates in real-time
  • Syncs subscription state to Convex on every change
const { isPremium, purchase, restore, refresh } = useSubscription();

Paywall Component (components/subscription/PaywallModal.tsx)

  • Single reusable component triggered from 6 strategic locations
  • Shows tier comparison, pricing, and contextual messaging
  • Handles purchase flow and restore directly

Paywall Trigger Strategy

Rather than a single onboarding paywall, Digero triggers contextual paywalls at moments of peak user motivation:

TriggerLocationContext
RECIPE_LIMIT_EXCEEDEDRecipe save flow"You've saved 10 recipes. Upgrade for unlimited."
SCAN_LIMIT_EXCEEDEDCookbook scanner"3 scans used this month. Upgrade for unlimited."
AI_CHAT_LIMIT_EXCEEDEDAI Sous Chef (hard lock at 5/5)Full-screen overlay at daily limit
EXCLUSIVE_CONTENTCreator channel Exclusive tabLocked recipe cards open paywall on tap
SHOP_DISCOUNTCreator Shop product pages"Subscribe to save $X.XX on this item"
(inline)AI Sous Chef (soft prompt at 4/5)Upgrade card injected into chat conversation

Server-Side Webhook Handler

POST /webhooks/revenuecatHMAC-SHA256 verification
EventAction
INITIAL_PURCHASESet subscription tier, detect trial, store RevenueCat user ID
RENEWALUpdate expiration, clear billing issues
CANCELLATIONMark cancelled, maintain access until expiration
EXPIRATIONRevert to free tier
BILLING_ISSUEFlag billing issue, maintain current tier
PRODUCT_CHANGEUpdate tier on upgrade/downgrade

After processing each event, the handler syncs the subscription tier to OneSignal as player tags for targeted push notification segmentation.

Data Flow

User taps "Subscribe" in PaywallModal
    │
    ▼
RevenueCat SDK processes purchase via App Store
    │
    ├──► Client: CustomerInfo listener fires
    │    └──► SubscriptionContext updates isPremium
    │         └──► syncSubscriptionFromClient() writes to Convex users table
    │
    └──► Server: RevenueCat sends webhook to /webhooks/revenuecat
         └──► Convex verifies HMAC signature
              └──► updateSubscription() writes to Convex users table
                   └──► Syncs tier to OneSignal for push targeting

Both paths (client SDK and server webhook) write to the same Convex users table, providing redundancy. The webhook is the source of truth for renewals, cancellations, and expirations that happen outside the app.

Feature Gating

Free Tier Limits

FeatureLimitEnforcement
Saved recipes10checkRecipeLimit() query before createRecipe mutation
Cookbook scans3 per 30-day rolling windowcheckScanLimit() query + recordScan() mutation
AI Sous Chef5 messages per dayuseAIChatLimit() hook with Convex daily counter
Exclusive contentLockedisPremium check in UI, no API exposure
Creator shop discount0%getMemberDiscountRate() returns 0 for free

Plus Tier

$4.99/mo

All free limits removed. 15% discount on creator shop products.

Creator Tier

$9.99/mo

All Plus features plus: creator dashboard, product shop, payout eligibility, RES multiplier bonuses.

Creator Economy Infrastructure

Recipe Engagement Score (RES)

Every user interaction with a creator's recipe generates engagement points stored in the recipeEngagement table:

ActionPointsRationale
Save1xLow-intent bookmark
Rating2xActive feedback
Share3xDistribution value
"I Made This" cook5xHighest intent — user actually cooked the recipe
Exclusive view2xSubscriber-only content engagement

Creator Tier Multipliers

Creator TierYouTube SubsRES Multiplier
Emerging10K+1.0x
Established100K+1.2x
Partner500K+1.5x

Payout Calculation

Monthly Subscription Revenue
    │
    ├──► App Store fee (15-30%)
    ├──► RevenueCat fee (~1.5%)
    │
    ▼
Net Revenue
    │
    ├──► Platform (50%)
    └──► Creator Pool (50%)
         │
         ▼
    Distributed by RES share:

    Creator Payout = (Creator RES × Tier Multiplier)
                     ────────────────────────────────  ×  Creator Pool
                           Total Platform RES

Implementation: getCreatorEarnings() in convex/creator.ts queries the recipeEngagement table, aggregates RES for the current period, and calculates the creator's estimated payout in real-time. The Creator Dashboard displays this data with a 7-day earnings chart and engagement breakdown.

Revenue Tracking

The revenueTransactions table stores every subscription event from the RevenueCat webhook with a full revenue breakdown:

{
  grossRevenue: number,      // Full subscription price
  appStoreFee: number,       // Apple/Google cut
  revenuecatFee: number,     // RevenueCat platform fee
  netRevenue: number,        // After all fees
  platformShare: number,     // Digero's 50%
  creatorPoolShare: number,  // Creator pool's 50%
}

Database Schema

users

FieldTypePurpose
clerkIdstringIdentity (indexed)
subscriptionStatus"free" | "plus" | "creator" | "trial"Current tier
subscriptionType"monthly" | "annual" | "lifetime"Billing period
subscriptionExpiresAtnumberUnix ms expiration
hasBillingIssuebooleanPayment failure flag
revenuecatUserIdstringWebhook correlation
onesignalPlayerIdstringPush notification targeting

creatorProfiles

FieldTypePurpose
userIdstringClerk user ID
youtubeChannelIdstringYouTube channel link
tier"emerging" | "established" | "partner"Partnership level
resMultipliernumberPayout multiplier (1.0-1.5x)
applicationStatus"pending" | "approved" | "rejected"Onboarding state
totalEarningsnumberDenormalized lifetime earnings

revenueTransactions — Stores every RevenueCat webhook event with gross/net revenue breakdown and creator pool allocation.

creatorPayouts — Monthly payout records per creator with RES share, payout amount, and payment status tracking.

recipeEngagement — Daily aggregated engagement metrics (saves, cooks, shares, ratings) per recipe per creator with calculated RES score.

OneSignal Integration

OneSignal is initialized after Clerk authentication and synced with subscription state for targeted messaging:

Player tags

subscription_status, subscription_type, recipe_count, followed_creators, is_creator

In-app message triggers

recipe_limit_reached, ai_chat_limit_warning, creator_exclusive_available, paywall_viewed

Push segments

Free users approaching limits, lapsed subscribers, creator followers

The RevenueCat webhook handler syncs tier changes to OneSignal after every subscription event, enabling real-time audience segmentation for conversion campaigns.

Built for RevenueCat Shipyard 2026