TinyKit Pro Docs

Product Management & Sync System Guide

Complete guide to TinyKit Pro's intelligent product management system that synchronizes products between your seed configuration, Stripe account, and Convex ...

Complete guide to TinyKit Pro's intelligent product management system that synchronizes products between your seed configuration, Stripe account, and Convex database.

System Overview

TinyKit Pro includes a comprehensive product management system with:

  • Smart Sync Logic: Automatically detects whether to sync from Stripe or create from seed configuration
  • Seed Configuration: TypeScript-based product catalog for consistent deployment across environments
  • Admin Interface: Comprehensive admin panel with intelligent status checking
  • Safety Checks: Prevents accidental operations with confirmation dialogs
  • Stripe Integration: Seamless integration with Stripe products, prices, and webhooks
  • Real-time Updates: Automatic database updates via Stripe webhooks

1. Product Seed Configuration

Configuration File Location

File: /convex/seeds/stripe_products.ts

This TypeScript file defines all products that can be created in your Stripe account.

Product Configuration Structure

interface ProductConfig {
  name: string; // Internal product name (kebab-case)
  displayName: string; // User-facing product name
  description: string; // Product description for marketing
  active: boolean; // Whether product is available for purchase
  type: SubscriptionType; // Product category
  accessLevel: number; // Feature access level (higher = more features)
  displayOrder: number; // UI display ordering (lower = higher priority)
  isRecommended?: boolean; // Show "Recommended" badge
  icon?: string; // Lucide icon name for UI
  features: string[]; // Feature list for marketing display
  prices: ProductPrice[]; // Associated pricing options
}

interface ProductPrice {
  amount: number; // Price in cents (USD)
  currency: "usd"; // Currency code
  interval?: BillingInterval; // Billing interval for subscriptions
  intervalCount?: number; // Billing interval multiplier (default: 1)
  type: "one_time" | "recurring"; // Price type
  active: boolean; // Whether price is available
  trialDays?: number; // Trial period length in days
}

Included Product Configurations

The seed file includes 7 pre-configured products:

Personal Plans

{
  name: "free",
  displayName: "Free",
  description: "Perfect for getting started with basic team collaboration",
  type: "personal",
  accessLevel: 1,
  displayOrder: 1,
  features: ["Basic workspace access", "Up to 2 team members", "Core features"],
  prices: [
    {
      amount: 0,
      currency: "usd",
      type: "recurring",
      interval: "month",
      active: true
    }
  ]
}

Team Plans

{
  name: "professional",
  displayName: "Professional",
  description: "Advanced features for growing teams",
  type: "org",
  accessLevel: 20,
  displayOrder: 2,
  isRecommended: true,
  icon: "Zap",
  features: [
    "Up to 20 team members",
    "Advanced project management",
    "Priority support",
    "Custom integrations"
  ],
  prices: [
    {
      amount: 2900,        // $29.00
      currency: "usd",
      type: "recurring",
      interval: "month",
      active: true
    },
    {
      amount: 29000,       // $290.00 (annual)
      currency: "usd",
      type: "recurring",
      interval: "year",
      active: true
    }
  ]
}

2. Smart Sync System

How Smart Sync Works

The system automatically determines the appropriate action based on current state:

  1. Database Check: Count existing products in Convex database
  2. Stripe Check: Count existing products in Stripe account
  3. Seed Validation: Verify seed configuration exists and is valid
  4. Action Determination: Choose sync from Stripe, create from seed, or show error

Sync Scenarios

Scenario 1: Products Already Exist

  • Condition: Database has products (> 0)
  • Action: disabled - Show Stripe Dashboard link
  • UI: Sync button disabled, Stripe Dashboard button available
  • Message: "You already have X products in your database. To manage products, use your Stripe dashboard directly."

Scenario 2: Sync from Stripe

  • Condition: Stripe has products, database is empty
  • Action: sync - Import existing Stripe products to database
  • UI: Confirmation dialog showing Stripe product count
  • Message: "Found X products in your Stripe account. This will sync all products and prices from Stripe to your database."

Scenario 3: Create from Seed

  • Condition: Neither Stripe nor database has products
  • Action: create - Create products in Stripe from seed, then sync to database
  • UI: Confirmation dialog showing seed product count
  • Message: "No products found in Stripe. This will create X products from your seed configuration in Stripe, then sync them to your database."

Scenario 4: Configuration Error

  • Condition: Missing seed file, invalid Stripe credentials, etc.
  • Action: error - Show error message and troubleshooting
  • UI: Disabled sync with error explanation

3. Admin Interface

Accessing Product Management

Navigate to /admin/products as an admin user.

Status Detection

The interface automatically checks:

// Status checking includes:
- Database product count
- Stripe product count
- Seed file validation
- User role permissions
- Stripe API connectivity

Confirmation Dialog System

Before any sync operation, users see a detailed confirmation dialog:

  • Current State: Shows counts for database, Stripe, and seed configuration
  • Action Description: Clear explanation of what will happen
  • Safety Information: Warnings about data operations and webhook behavior
  • Product Counts: Visual breakdown of products in each system
  • Stripe Dashboard Link: Direct access to Stripe when products exist

Interface States

When Products Exist

// Disabled sync + Stripe Dashboard access
<Button variant="outline" onClick={openStripeDashboard}>
  <ExternalLink className="h-4 w-4 mr-2" />
  Stripe Dashboard
</Button>
<Button disabled>
  Sync from Stripe (Products exist)
</Button>

When No Products Exist

// Active sync button with confirmation dialog
<SyncProductsDialog>
  <Button>
    <RefreshCw className="h-4 w-4 mr-2" />
    Sync from Stripe
  </Button>
</SyncProductsDialog>

4. Backend Implementation

Core Sync Function

Function: syncProductsFromStripe Location: /convex/billing/public/mutations.ts

export const syncProductsFromStripe = mutation({
  args: {},
  handler: async (
    ctx,
  ): Promise<{
    products: number;
    prices: number;
    source: "stripe" | "seed";
  }> => {
    // Check Stripe for existing products
    const stripeProducts = await stripe.products.list({ active: true });

    if (stripeProducts.data.length > 0) {
      // Sync existing products from Stripe to database
      return await syncFromStripe(ctx);
    } else {
      // Create products from seed configuration, then sync to database
      return await createFromSeedThenSync(ctx);
    }
  },
});

Status Checking Function

Function: checkProductsStatus Location: /convex/billing/public/actions.ts

export const checkProductsStatus = action({
  args: {},
  handler: async (
    ctx,
  ): Promise<{
    hasDbProducts: boolean;
    dbProductCount: number;
    hasStripeProducts: boolean;
    stripeProductCount: number;
    hasSeedProducts: boolean;
    seedProductCount: number;
    action: "disabled" | "sync" | "create" | "error";
    message: string;
  }> => {
    // Comprehensive status checking logic
    // Returns detailed state information for UI
  },
});

5. Webhook Integration

Automatic Synchronization

Product updates in Stripe automatically sync to the database via webhooks:

Supported Webhook Events

  • product.created - New products automatically added to database
  • product.updated - Product changes synchronized in real-time
  • price.created - New prices automatically added to database
  • price.updated - Price changes synchronized

Webhook Endpoint

Location: /convex/http.ts Endpoint: /stripe

// Webhook processing for product events
switch (event.type) {
  case "product.created":
    await syncProductToDatabase(event.data.object);
    break;
  case "product.updated":
    await updateProductInDatabase(event.data.object);
    break;
  case "price.created":
    await syncPriceToDatabase(event.data.object);
    break;
  // ... additional event handling
}

6. Development Workflow

Setting Up Products (Clean Environment)

  1. Access Admin Panel: Navigate to /admin/products as admin user
  2. Check Status: System automatically detects empty state
  3. Review Products: System shows "Create from Seed" option
  4. Confirm Creation: Click "Sync from Stripe" and review confirmation dialog
  5. Execute Creation: System creates products in Stripe from seed configuration
  6. Automatic Sync: Webhooks automatically populate database
  7. Verify Results: Check that products appear in admin interface

Managing Existing Products

  1. Use Stripe Dashboard: Manage products directly in Stripe dashboard
  2. Automatic Sync: Changes sync to database automatically via webhooks
  3. Admin Monitoring: Use admin panel to monitor product status
  4. Database Integrity: System maintains consistency between Stripe and database

7. Environment Migration

Development to Production

  1. Stripe Setup: Configure production Stripe account with live API keys
  2. Product Creation: Use admin interface to create products from seed configuration
  3. Webhook Configuration: Set up production webhook endpoints
  4. Verification: Confirm products appear correctly in database
  5. Testing: Test full subscription flow with test cards in live mode

Staging Environment

  1. Separate Stripe Account: Use separate Stripe account for staging
  2. Environment Variables: Configure staging-specific environment variables
  3. Product Sync: Use same seed configuration for consistency
  4. Webhook Testing: Test webhook delivery to staging environment

8. API Reference

Admin Functions

All product management functions follow the *Admin suffix pattern:

Queries

// Get all products for admin management
api.billing.public.queries.listAllProductsAdmin;

// Search products with filters
api.billing.public.queries.searchProductsAdmin;

Actions

// Smart sync from Stripe or create from seed
api.billing.public.mutations.syncProductsFromStripe;

// Check current system status for smart UI
api.billing.public.actions.checkProductsStatus;

Product Data Structure

// Products stored in Convex database
interface Product {
  _id: Id<"products">;
  stripeProductId: string; // Stripe product ID
  name: string; // Product name
  description?: string; // Product description
  active: boolean; // Availability status
  displayOrder?: number; // UI ordering
  accessLevel?: number; // Feature access level
  type?: SubscriptionType; // Product category
  isRecommended?: boolean; // Marketing flag
  icon?: string; // UI icon
  features?: string[]; // Feature list
  createdAt: number; // Creation timestamp
  updatedAt: number; // Last update timestamp
}

// Prices stored with product reference
interface Price {
  _id: Id<"prices">;
  stripePriceId: string; // Stripe price ID
  productId: Id<"products">; // Reference to product
  amount: number; // Price in cents
  currency: string; // Currency code
  interval?: string; // Billing interval
  intervalCount?: number; // Interval multiplier
  type: "one_time" | "recurring"; // Price type
  active: boolean; // Availability status
  trialDays?: number; // Trial period
  createdAt: number;
  updatedAt: number;
}

9. Troubleshooting

Common Issues

"Unauthorized: Admin access required" error

  • Solution: Ensure user has admin role
  • Check: Verify authentication is working properly
  • Debug: Check user role in database

Products not syncing from Stripe

  • Solution: Check Stripe API credentials in environment variables
  • Verify: Webhook endpoint is configured correctly
  • Test: Use stripe webhook forward to test locally

Seed file not found error

  • Solution: Ensure /convex/seeds/stripe_products.ts exists
  • Check: Verify file is properly formatted TypeScript
  • Validate: Check for syntax errors with bun typecheck

Webhooks not updating database

  • Solution: Verify webhook signing secret matches environment variable
  • Check: Webhook URL is accessible from Stripe's servers
  • Monitor: Webhook delivery in Stripe dashboard

Sync button not opening dialog

  • Cause: Common issue with click handler conflicts
  • Solution: Fixed by using plain Button as AlertDialog trigger
  • Check: Ensure SyncButton component is properly configured

Infinite API calls during status checking

  • Cause: useEffect dependency issues
  • Solution: Fixed by stabilizing dependencies with useCallback
  • Check: Monitor network tab for excessive API calls

Debug Commands

# Monitor Convex function logs during sync
npx convex logs --tail | grep "product\|price\|sync"

# Check webhook delivery status
stripe logs tail

# View current products in database
npx convex dashboard
# Navigate to 'products' and 'prices' tables

# Test product sync manually
# In Convex dashboard, call syncProductsFromStripe mutation

# Check environment variables
npx convex env list | grep STRIPE

Performance Debugging

# Monitor sync operation performance
npx convex logs --tail | grep -E "(sync|create).*products"

# Check Stripe API rate limits
stripe logs tail | grep -i "rate"

# Monitor webhook processing time
npx convex logs --tail | grep "webhook.*product"

10. Best Practices

Seed File Management

  • Version Control: Always commit seed file changes to track product evolution
  • Type Safety: Use TypeScript interfaces to prevent configuration errors
  • Documentation: Include comprehensive product descriptions and feature lists
  • Pricing Strategy: Plan price points and trial periods carefully
  • Consistency: Use same seed file across all environments

Environment Management

  • Consistent Configuration: Use same seed file across development, staging, and production
  • Webhook Testing: Test webhook integration thoroughly in staging environment
  • Product IDs: Never hardcode Stripe IDs - let system generate them
  • Database Cleanup: Use admin interface to manage products, avoid manual database edits

Production Deployment

  • Stripe Configuration: Set up production webhook endpoints before deployment
  • Environment Variables: Ensure all Stripe keys are configured for production
  • Product Migration: Use sync system to populate products consistently
  • Monitoring: Monitor webhook delivery and product sync status post-deployment
  • Backup: Export product configuration before making changes

Security Considerations

  • API Key Security: Store Stripe keys securely in environment variables
  • Admin Access: Restrict product management to appropriate admin roles
  • Webhook Verification: Always verify webhook signatures
  • Audit Logging: Monitor product changes and sync operations

← Previous: SEO & OG Images | ← Back to Guides

On this page

Ship your startup faster. In minutes.

Get TinyKit Pro