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:
- Database Check: Count existing products in Convex database
- Stripe Check: Count existing products in Stripe account
- Seed Validation: Verify seed configuration exists and is valid
- 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 connectivityConfirmation 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 databaseproduct.updated- Product changes synchronized in real-timeprice.created- New prices automatically added to databaseprice.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)
- Access Admin Panel: Navigate to
/admin/productsas admin user - Check Status: System automatically detects empty state
- Review Products: System shows "Create from Seed" option
- Confirm Creation: Click "Sync from Stripe" and review confirmation dialog
- Execute Creation: System creates products in Stripe from seed configuration
- Automatic Sync: Webhooks automatically populate database
- Verify Results: Check that products appear in admin interface
Managing Existing Products
- Use Stripe Dashboard: Manage products directly in Stripe dashboard
- Automatic Sync: Changes sync to database automatically via webhooks
- Admin Monitoring: Use admin panel to monitor product status
- Database Integrity: System maintains consistency between Stripe and database
7. Environment Migration
Development to Production
- Stripe Setup: Configure production Stripe account with live API keys
- Product Creation: Use admin interface to create products from seed configuration
- Webhook Configuration: Set up production webhook endpoints
- Verification: Confirm products appear correctly in database
- Testing: Test full subscription flow with test cards in live mode
Staging Environment
- Separate Stripe Account: Use separate Stripe account for staging
- Environment Variables: Configure staging-specific environment variables
- Product Sync: Use same seed configuration for consistency
- 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
adminrole - 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 forwardto test locally
Seed file not found error
- Solution: Ensure
/convex/seeds/stripe_products.tsexists - 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 STRIPEPerformance 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
SEO & Open Graph Images Guide
Complete guide to configuring TinyKit Pro's SEO optimization features, including dynamic Open Graph images, sitemap generation, and search engine optimization.
Resend Audience API Integration
TinyKit Pro includes a comprehensive integration with Resend's Audience API for advanced contact management, segmentation, and email marketing campaigns.