-
-
Notifications
You must be signed in to change notification settings - Fork 7
Implement Standard Tier: 1/mo, 8000 credits, billed yearly #428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: refactor/collaboration-ui-integration
Are you sure you want to change the base?
Implement Standard Tier: 1/mo, 8000 credits, billed yearly #428
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughIntroduces a new Standard Tier pricing configuration system across environment variables, configuration file, and subscription utility module. Adds tier definitions with credits, pricing, and billing cycle management alongside environment-driven configuration values and tier lookup utilities. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ 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. Comment |
|
|
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
Compliance status legend🟢 - Fully Compliant🟡 - Partial Compliant 🔴 - Not Compliant ⚪ - Requires Further Human Verification 🏷️ - Compliance label |
||||||||||||||||||||||||
PR Code Suggestions ✨Explore these optional code suggestions:
|
|||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main issue is configuration duplication and drift risk: tier data exists in both config/pricing.json and lib/utils/subscription.ts with different fields and naming, making it unclear which is authoritative. There’s also pricing semantic ambiguity (STANDARD_TIER_MONTHLY_PRICE vs a yearly billing cycle) that could lead to incorrect billing amounts. Additionally, env parsing via Number(...) || default can mask misconfiguration, and getTierConfig() silently falling back to free can hide invalid tier inputs.
Summary of changes
What changed
- Added a new pricing configuration file at
config/pricing.jsondefiningfreeandstandardtiers (including credits, price, billing cycle, and aprice_id_envkey). - Added
lib/utils/subscription.tsimplementing tier constants (TIERS), aTierConfiginterface, in-code tier configs (TIER_CONFIGS) using environment-variable overrides, and agetTierConfig()helper that falls back tofree.
Notable details
standardis configured as8000credits withprice: 41andbilling cycle: yearlyin JSON, while the TS utility readsSTANDARD_TIER_MONTHLY_PRICEandSTANDARD_TIER_BILLING_CYCLEfrom env with defaults.
| { | ||
| "tiers": { | ||
| "free": { | ||
| "name": "Free", | ||
| "credits": 0, | ||
| "price": 0 | ||
| }, | ||
| "standard": { | ||
| "name": "Standard", | ||
| "credits": 8000, | ||
| "price": 41, | ||
| "billing_cycle": "yearly", | ||
| "price_id_env": "STANDARD_TIER_PRICE_ID" | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config/pricing.json and lib/utils/subscription.ts define tier configs in two separate places, but with different shapes and naming (e.g., billing_cycle vs billingCycle, price_id_env only exists in JSON). This creates an immediate risk of drift (values and semantics diverging) and makes it unclear which source is authoritative at runtime.
Suggestion
Pick a single source of truth for tier configuration.
Option A (recommended): Load and normalize config from config/pricing.json in subscription.ts, mapping JSON keys to TS keys:
billing_cycle->billingCycle- include
priceIdEnv(or similar) inTierConfig
Option B: Remove config/pricing.json and keep configuration in code/env only.
If you want, reply with "@CharlieHelps yes please" and I can add a commit that loads pricing.json in subscription.ts and normalizes it into a typed TIER_CONFIGS map (eliminating duplication).
| [TIERS.STANDARD]: { | ||
| name: 'Standard', | ||
| credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000, | ||
| price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41, | ||
| billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The environment variable name STANDARD_TIER_MONTHLY_PRICE conflicts with the context/intent of "1/mo, billed yearly" and the JSON billing_cycle: "yearly". With current defaults, price is set to 41 even though it’s unclear whether that is meant to be monthly or yearly price. This ambiguity can cause incorrect billing amounts depending on how price is consumed downstream.
Suggestion
Clarify the price semantics and encode them explicitly.
- Rename env var to match meaning, e.g.
STANDARD_TIER_PRICE_PER_BILLING_CYCLEorSTANDARD_TIER_YEARLY_PRICE. - Alternatively store both
monthlyPriceandyearlyPriceand compute based onbillingCycle.
Example:
export interface TierConfig {
name: string;
credits: number;
billingCycle: 'monthly' | 'yearly';
priceCents: number; // be explicit about units
}
priceCents: Number(process.env.STANDARD_TIER_YEARLY_PRICE_CENTS) || 4100,Reply with "@CharlieHelps yes please" if you’d like me to add a commit that renames the env var(s) and updates the config accordingly (including a safer price/unit representation).
| [TIERS.STANDARD]: { | ||
| name: 'Standard', | ||
| credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000, | ||
| price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41, | ||
| billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using Number(process.env.X) || default will treat valid 0 values as falsy and silently fall back to defaults. While 0 probably isn't intended for paid tiers, this pattern is fragile and can also mask misconfiguration (e.g., Number('') becomes 0).
Suggestion
Use nullish coalescing on the raw env value and validate numeric parsing explicitly.
Example:
const creditsRaw = process.env.STANDARD_TIER_CREDITS;
const credits = creditsRaw == null ? 8000 : Number(creditsRaw);
if (!Number.isFinite(credits) || credits < 0) throw new Error('Invalid STANDARD_TIER_CREDITS');This prevents silent fallback and avoids treating "" as 0.
Reply with "@CharlieHelps yes please" if you want me to add a commit implementing robust parsing helpers (e.g., getEnvNumber(name, default) + validation).
lib/utils/subscription.ts
Outdated
| export const TIER_CONFIGS: Record<string, TierConfig> = { | ||
| [TIERS.FREE]: { | ||
| name: 'Free', | ||
| credits: 0, | ||
| price: 0, | ||
| billingCycle: 'monthly', | ||
| }, | ||
| [TIERS.STANDARD]: { | ||
| name: 'Standard', | ||
| credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000, | ||
| price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41, | ||
| billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly', | ||
| }, | ||
| }; | ||
|
|
||
| export function getTierConfig(tier: string): TierConfig { | ||
| return TIER_CONFIGS[tier] || TIER_CONFIGS[TIERS.FREE]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIER_CONFIGS is typed as Record<string, TierConfig>, but getTierConfig(tier: string) can accept any string and silently fall back to free. That makes it easy to pass an invalid tier without noticing (potentially granting free-tier behavior where it shouldn’t).
Suggestion
Make tier handling stricter and type-safe:
- Define
type Tier = typeof TIERS[keyof typeof TIERS]and accepttier: Tierwhere possible. - If you must accept arbitrary input (e.g., from requests), return an object that indicates validity or throw for unknown tiers in internal code paths.
Example:
type Tier = typeof TIERS[keyof typeof TIERS];
export function getTierConfig(tier: Tier): TierConfig {
return TIER_CONFIGS[tier];
}
export function parseTier(input: string): Tier {
if (input === TIERS.FREE || input === TIERS.STANDARD) return input;
return TIERS.FREE;
}Reply with "@CharlieHelps yes please" if you’d like me to add a commit introducing a Tier union type and splitting parseTier() from getTierConfig() to avoid silent mistakes.
|
@coderabbitai can you review this and make it work perfectly. |
|
@coderabbitai I need the credits to preview at the top of the chat-history preview bar. |
🧩 Analysis chain
🏁 Script executed: Length of output: 2493 🏁 Script executed: Length of output: 1631 🏁 Script executed: Length of output: 8172
🚨 Critical Issues1. Price Discrepancy
This needs to be clarified. Which is correct? 2. No Database IntegrationThe // Missing from users table:
tier: varchar('tier', { length: 50 }).default('free'),
credits: integer('credits').default(0),
stripeCustomerId: text('stripe_customer_id'),
stripeSubscriptionId: text('stripe_subscription_id'),
subscriptionStatus: varchar('subscription_status', { length: 50 }),3. No Stripe Integration
4. Subscription Utility Not Connected
5. Redundant Configuration
📋 What Needs to Be DoneTo make this work perfectly, here's what should be implemented: Phase 1: Foundation (Current PR)
Phase 2: Payment Integration
Phase 3: Credit System
🛠️ Immediate Fixes NeededWould you like me to:
I can help you build the complete solution step-by-step. Let me know which parts you'd like me to tackle first! ✅ Actions performedReview triggered.
|
|
@coderabbitai I need call to purchase credits pop up as soon as user is authenticated. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 446 🏁 Script executed: Length of output: 10186 🏁 Script executed: Length of output: 4199 🏁 Script executed: Length of output: 7354
🏁 Script executed: Length of output: 428 Perfect! I can see the structure now. Let me plan the implementation to add credits display at the top of the chat-history preview bar. [plan_code_changes] Task: Add Credits Display at Top of Chat History Preview Bar
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 5218 🏁 Script executed: Length of output: 13640
[plan_code_changes] Implementation Plan: Purchase Credits Pop-up on AuthenticationOverview:
Components to create:
SummaryThis implementation will:
The dialog will appear 1 second after authentication, giving users a smooth onboarding experience without being too intrusive. Users can choose to continue with the free tier or upgrade to standard. Would you also like me to add a manual trigger for this dialog (e.g., a button in the header to re-open it)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @.env:
- Around line 10-15: Rename the committed .env to .env.example and replace
real-looking values with placeholders so no secrets are checked in; update the
variables STANDARD_TIER_PRICE_ID, STANDARD_TIER_CREDITS,
STANDARD_TIER_MONTHLY_PRICE, and STANDARD_TIER_BILLING_CYCLE to placeholder
values (e.g., PRICE_ID_PLACEHOLDER) and add a comment next to
STANDARD_TIER_PRICE_ID indicating it must be replaced with a real Stripe price
ID in production; also add .env to .gitignore to prevent local env files from
being committed.
In `@lib/utils/subscription.ts`:
- Line 24: The billingCycle assignment currently unsafely casts
process.env.STANDARD_TIER_BILLING_CYCLE to 'monthly'|'yearly'; instead validate
the env value against the allowed set before using it (e.g., check if
process.env.STANDARD_TIER_BILLING_CYCLE === 'monthly' or 'yearly') and only
accept it when it matches, otherwise fall back to 'yearly'; implement this
validation inline where billingCycle is set or extract it to a helper like
parseBillingCycle/validateBillingCycle and use that to produce the final value.
- Around line 1-30: The subscription exports (TIERS, TIER_CONFIGS,
getTierConfig) are not re-exported from the utils index so other modules can't
import them; open the utils index module and add re-exports for TIERS,
TIER_CONFIGS, and getTierConfig (re-export them from the subscription module or
explicitly export them) so those symbols become available across the codebase.
♻️ Duplicate comments (4)
config/pricing.json (1)
1-16: Configuration file is currently unused.This JSON file duplicates tier definitions from
lib/utils/subscription.tswith different key naming conventions (billing_cyclevsbillingCycle,price_id_envonly here). As noted previously, this creates drift risk and ambiguity about the authoritative source.Additionally, this file is not imported or referenced anywhere in the codebase. Either integrate it as the single source of truth (loading it from
subscription.ts) or remove it to avoid stale configuration.#!/bin/bash # Verify if pricing.json is imported or referenced anywhere rg -l "pricing\.json" --type ts --type js --type tsx rg -l "config/pricing" --type ts --type jslib/utils/subscription.ts (3)
6-11: Interface looks good, but clarify price semantics.The
pricefield is ambiguous—it's unclear whether this represents a monthly price, yearly price, or price per billing cycle. This was flagged previously. Consider renaming topricePerBillingCycleor adding separatemonthlyPrice/yearlyPricefields.
22-23: Fragile environment variable parsing.Using
Number(env) || defaulttreats valid0as falsy and falls back silently. While0may not be intended for paid tiers, this pattern can mask misconfiguration (e.g.,Number('')becomes0, then falls back). This was flagged in a previous review.
28-30: Silent fallback to FREE tier for unknown input.
getTierConfigaccepts any string and silently returns the free tier for invalid input. This was flagged previously—consider stricter typing or explicit error handling for internal code paths.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
.envconfig/pricing.jsonlib/utils/subscription.ts
🧰 Additional context used
🪛 dotenv-linter (4.0.0)
.env
[warning] 12-12: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 13-13: [UnorderedKey] The STANDARD_TIER_CREDITS key should go before the STANDARD_TIER_PRICE_ID key
(UnorderedKey)
[warning] 14-14: [UnorderedKey] The STANDARD_TIER_MONTHLY_PRICE key should go before the STANDARD_TIER_PRICE_ID key
(UnorderedKey)
[warning] 15-15: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 15-15: [UnorderedKey] The STANDARD_TIER_BILLING_CYCLE key should go before the STANDARD_TIER_CREDITS key
(UnorderedKey)
🔇 Additional comments (1)
lib/utils/subscription.ts (1)
1-4: LGTM on the TIERS constant definition.Using
as constprovides proper literal types for the tier keys, enabling type-safe usage downstream.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
|
||
| # Standard Tier Configuration | ||
| STANDARD_TIER_PRICE_ID="price_standard_41_yearly" | ||
| STANDARD_TIER_CREDITS=8000 | ||
| STANDARD_TIER_MONTHLY_PRICE=41 | ||
| STANDARD_TIER_BILLING_CYCLE="yearly" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider renaming to .env.example and documenting placeholders.
Committing a .env file can accidentally leak secrets if real values are added later. The standard practice is to commit .env.example with placeholder values and add .env to .gitignore.
Also, price_standard_41_yearly appears to be a placeholder Stripe price ID—consider adding a comment indicating it must be replaced with a real Stripe price ID in production.
Suggested changes
# Standard Tier Configuration
+# Replace STANDARD_TIER_PRICE_ID with your actual Stripe price ID from the dashboard
-STANDARD_TIER_PRICE_ID="price_standard_41_yearly"
+STANDARD_TIER_PRICE_ID="price_xxx" # Get from Stripe Dashboard
STANDARD_TIER_CREDITS=8000
STANDARD_TIER_MONTHLY_PRICE=41
STANDARD_TIER_BILLING_CYCLE="yearly"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Standard Tier Configuration | |
| STANDARD_TIER_PRICE_ID="price_standard_41_yearly" | |
| STANDARD_TIER_CREDITS=8000 | |
| STANDARD_TIER_MONTHLY_PRICE=41 | |
| STANDARD_TIER_BILLING_CYCLE="yearly" | |
| # Standard Tier Configuration | |
| # Replace STANDARD_TIER_PRICE_ID with your actual Stripe price ID from the dashboard | |
| STANDARD_TIER_PRICE_ID="price_xxx" # Get from Stripe Dashboard | |
| STANDARD_TIER_CREDITS=8000 | |
| STANDARD_TIER_MONTHLY_PRICE=41 | |
| STANDARD_TIER_BILLING_CYCLE="yearly" |
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 12-12: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 13-13: [UnorderedKey] The STANDARD_TIER_CREDITS key should go before the STANDARD_TIER_PRICE_ID key
(UnorderedKey)
[warning] 14-14: [UnorderedKey] The STANDARD_TIER_MONTHLY_PRICE key should go before the STANDARD_TIER_PRICE_ID key
(UnorderedKey)
[warning] 15-15: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 15-15: [UnorderedKey] The STANDARD_TIER_BILLING_CYCLE key should go before the STANDARD_TIER_CREDITS key
(UnorderedKey)
🤖 Prompt for AI Agents
In @.env around lines 10 - 15, Rename the committed .env to .env.example and
replace real-looking values with placeholders so no secrets are checked in;
update the variables STANDARD_TIER_PRICE_ID, STANDARD_TIER_CREDITS,
STANDARD_TIER_MONTHLY_PRICE, and STANDARD_TIER_BILLING_CYCLE to placeholder
values (e.g., PRICE_ID_PLACEHOLDER) and add a comment next to
STANDARD_TIER_PRICE_ID indicating it must be replaced with a real Stripe price
ID in production; also add .env to .gitignore to prevent local env files from
being committed.
| export const TIERS = { | ||
| FREE: 'free', | ||
| STANDARD: 'standard', | ||
| } as const; | ||
|
|
||
| export interface TierConfig { | ||
| name: string; | ||
| credits: number; | ||
| price: number; | ||
| billingCycle: 'monthly' | 'yearly'; | ||
| } | ||
|
|
||
| export const TIER_CONFIGS: Record<string, TierConfig> = { | ||
| [TIERS.FREE]: { | ||
| name: 'Free', | ||
| credits: 0, | ||
| price: 0, | ||
| billingCycle: 'monthly', | ||
| }, | ||
| [TIERS.STANDARD]: { | ||
| name: 'Standard', | ||
| credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000, | ||
| price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41, | ||
| billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly', | ||
| }, | ||
| }; | ||
|
|
||
| export function getTierConfig(tier: string): TierConfig { | ||
| return TIER_CONFIGS[tier] || TIER_CONFIGS[TIERS.FREE]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify if subscription.ts is imported anywhere
echo "=== Checking for imports of subscription module ==="
rg "from.*subscription|import.*subscription" --type ts --type tsx
echo -e "\n=== Checking for direct utils/subscription imports ==="
rg "utils/subscription" --type ts --type tsx
echo -e "\n=== Checking lib/utils/index.ts ==="
if [ -f "lib/utils/index.ts" ]; then
cat -n "lib/utils/index.ts"
else
echo "lib/utils/index.ts not found"
fd -t f "index.ts" lib/utils
fiRepository: QueueLab/QCX
Length of output: 5074
🏁 Script executed:
#!/bin/bash
# Check if subscription.ts exists
echo "=== Checking for subscription.ts file ==="
fd -t f "subscription.ts" lib/
echo -e "\n=== Broad search for TIERS usage ==="
rg "TIERS\." --type ts --type tsx | head -20
echo -e "\n=== Broad search for getTierConfig usage ==="
rg "getTierConfig" --type ts --type tsx | head -20
echo -e "\n=== Broad search for TIER_CONFIGS usage ==="
rg "TIER_CONFIGS" --type ts --type tsx | head -20Repository: QueueLab/QCX
Length of output: 353
Export subscription configuration module from lib/utils/index.ts.
The subscription utility module is defined but not exported from lib/utils/index.ts, making TIERS, TIER_CONFIGS, and getTierConfig inaccessible to the rest of the application. Export these exports so the module becomes integrated and usable across the codebase.
🤖 Prompt for AI Agents
In `@lib/utils/subscription.ts` around lines 1 - 30, The subscription exports
(TIERS, TIER_CONFIGS, getTierConfig) are not re-exported from the utils index so
other modules can't import them; open the utils index module and add re-exports
for TIERS, TIER_CONFIGS, and getTierConfig (re-export them from the subscription
module or explicitly export them) so those symbols become available across the
codebase.
lib/utils/subscription.ts
Outdated
| name: 'Standard', | ||
| credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000, | ||
| price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41, | ||
| billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsafe type cast without validation.
Casting process.env.STANDARD_TIER_BILLING_CYCLE directly to 'monthly' | 'yearly' allows any string value (including typos like "yeerly") to pass through without error, potentially causing downstream issues.
Suggested fix with validation
+const VALID_BILLING_CYCLES = ['monthly', 'yearly'] as const;
+type BillingCycle = typeof VALID_BILLING_CYCLES[number];
+
+function parseBillingCycle(value: string | undefined, defaultValue: BillingCycle): BillingCycle {
+ if (value && VALID_BILLING_CYCLES.includes(value as BillingCycle)) {
+ return value as BillingCycle;
+ }
+ return defaultValue;
+}
[TIERS.STANDARD]: {
name: 'Standard',
credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000,
price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41,
- billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly',
+ billingCycle: parseBillingCycle(process.env.STANDARD_TIER_BILLING_CYCLE, 'yearly'),
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| billingCycle: (process.env.STANDARD_TIER_BILLING_CYCLE as 'monthly' | 'yearly') || 'yearly', | |
| const VALID_BILLING_CYCLES = ['monthly', 'yearly'] as const; | |
| type BillingCycle = typeof VALID_BILLING_CYCLES[number]; | |
| function parseBillingCycle(value: string | undefined, defaultValue: BillingCycle): BillingCycle { | |
| if (value && VALID_BILLING_CYCLES.includes(value as BillingCycle)) { | |
| return value as BillingCycle; | |
| } | |
| return defaultValue; | |
| } | |
| [TIERS.STANDARD]: { | |
| name: 'Standard', | |
| credits: Number(process.env.STANDARD_TIER_CREDITS) || 8000, | |
| price: Number(process.env.STANDARD_TIER_MONTHLY_PRICE) || 41, | |
| billingCycle: parseBillingCycle(process.env.STANDARD_TIER_BILLING_CYCLE, 'yearly'), | |
| }, |
🤖 Prompt for AI Agents
In `@lib/utils/subscription.ts` at line 24, The billingCycle assignment currently
unsafely casts process.env.STANDARD_TIER_BILLING_CYCLE to 'monthly'|'yearly';
instead validate the env value against the allowed set before using it (e.g.,
check if process.env.STANDARD_TIER_BILLING_CYCLE === 'monthly' or 'yearly') and
only accept it when it matches, otherwise fall back to 'yearly'; implement this
validation inline where billingCycle is set or extract it to a helper like
parseBillingCycle/validateBillingCycle and use that to produce the final value.
- Added 'credits' field to user schema in 'lib/db/schema.ts'. - Created API route 'app/api/user/credits/route.ts' to fetch user credits. - Added 'CreditsDisplay' and 'PurchaseCreditsPopup' components in 'components/credits/'. - Integrated credit display into 'app/layout.tsx' (or relevant UI). - Updated 'lib/utils/subscription.ts' to include credit-based logic. - Modified 'components/sidebar/chat-history-client.tsx' for standard tier adjustments. - Added '.env.example' and updated '.gitignore'.
c0074af to
f30205b
Compare
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 3076 🏁 Script executed: Length of output: 2178 🏁 Script executed: Length of output: 770
🚨 Issue
|
|
@coderabbitai figure out why the credit/stripe system is not functional and give the steps to fix it. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 3466 🏁 Script executed: Length of output: 7613
🔍 Diagnostic Summary✅ What's Working:
❌ What's Broken:
🛠️ Step-by-Step Fix PlanSTEP 1: Fix OAuth Errors (CRITICAL - Do This First!)Your Action: Add these to your # Add these lines to .env
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.your-anon-key-hereWhere to find these values:
Also add to Vercel:
STEP 2: Show Credits in History SidebarThe File: Change: import { ChatHistoryClient } from './sidebar/chat-history-client'
import { Suspense } from 'react'
import { HistorySkeleton } from './history-skelton'
+import { CreditsDisplay } from './credits/credits-display'
type HistoryProps = {
location: 'sidebar' | 'header'
}
export function History({ location }: HistoryProps) {
return (
<Sheet>
<SheetTrigger asChild>
<Button
variant="ghost"
size="icon"
className={cn({
'rounded-full text-foreground/30': location === 'sidebar'
})}
data-testid="history-button"
>
{location === 'header' ? <Menu /> : <Sprout size={16} />}
</Button>
</SheetTrigger>
<SheetContent className="w-64 rounded-tl-xl rounded-bl-xl" data-testid="history-panel">
<SheetHeader>
<SheetTitle className="flex items-center gap-1 text-sm font-normal mb-2">
<HistoryIcon size={14} />
History
</SheetTitle>
</SheetHeader>
+ <CreditsDisplay className="mb-4" />
<div className="my-2 h-full pb-12 md:pb-10">
<Suspense fallback={<HistorySkeleton />}>
<ChatHistoryClient />
</Suspense>
</div>
</SheetContent>
</Sheet>
)
}STEP 3: Fix the Upgrade ButtonCurrently the "Upgrade to Standard" button just logs to console. Make it redirect to Stripe. File: Change: const handleUpgrade = (tier: string) => {
- // Placeholder for upgrade logic
- // In a real app, this would likely redirect to Stripe Checkout
- console.log(`Upgrading to ${tier}`);
+ // Redirect to Stripe checkout
+ const stripeUrl = 'https://buy.stripe.com/3cIaEX3tRcur9EM7ss';
+ window.open(stripeUrl, '_blank');
+ setIsOpen(false);
}STEP 4: Install Stripe SDK (For Future Webhook Integration)While your current setup uses direct Stripe links, you'll eventually need the SDK for webhooks. Run: npm install stripe
# or
yarn add stripe
# or
pnpm add stripeSTEP 5: Configure Supabase Redirect URLsIn your Supabase Dashboard:
STEP 6: Update .env.exampleHelp other developers by documenting required env vars. File: Add: +# Supabase (Required for Authentication)
+NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
+NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
+
# Stripe Configuration
STANDARD_TIER_PRICE_ID=price_placeholder # must be real Stripe price ID in prod
STANDARD_TIER_CREDITS=8000
STANDARD_TIER_MONTHLY_PRICE=41
STANDARD_TIER_BILLING_CYCLE=yearly📋 Testing ChecklistAfter applying all fixes:
🎯 Priority Order
🚀 Quick Start (Minimal Viable Fix)If you want the fastest path to working, do these 3 things:
That's it! Your system will be functional. 💡 Future Enhancements (Not Required Now)Once the basics work, you can add:
Would you like me to create the Stripe webhook integration as well, or are these fixes sufficient for now? |
…display - Improved error logging in auth callback to diagnose 401 Unauthorized issues. - Integrated CreditsDisplay component into the history sidebar. - Fixed the upgrade button in PurchaseCreditsPopup to redirect to Stripe checkout. - Added required Supabase environment variables to .env.example. - Installed the stripe package to support payment processing. - Ensured successful production build and clean repository state.
…on-2704938752808797816 Fix OAuth Errors and Integrate Credits Display
…g of purchase popup
|
@coderabbitai the user auth-supabase-stripe save chat and check credit system should be well integrated the user should have a seamless user experience. check the code for any logical error |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 24386
🚨 CRITICAL LOGICAL ERRORS FOUNDError
|
| Error | Fix | Impact |
|---|---|---|
#1 No credit consumption |
Add checkAndConsumeCredits() middleware |
|
#2 No user initialization |
Add user creation in auth callback | |
#3 No Stripe webhook |
Create /api/webhooks/stripe |
|
#4 Popup not integrated |
Create & integrate PurchaseCreditsProvider |
🔴 HIGH - Improves user onboarding |
#5 No checkout API |
Create /api/checkout |
🔴 HIGH - Enables payment tracking |
🚀 Implementation Order
- First: User initialization (Error
#2) - Prevents all downstream errors - Second: Checkout API + Webhook (Errors
#3,#5) - Enables payments to work - Third: Credit consumption (Error
#1) - Enforces the credit system - Fourth: Provider integration (Error
#4) - Improves UX
✅ After These Fixes, The Complete Flow Will Be:
- User signs up via OAuth → Auto-created in database with 0 credits (free tier) ✅
- User opens app → Purchase popup shows after 2 seconds ✅
- User clicks "Upgrade" → Proper Stripe checkout with user metadata ✅
- User pays → Stripe webhook updates credits to 8000 ✅
- User creates chat → 10 credits deducted, 7990 remaining ✅
- User runs out of credits → 403 error, prompt to upgrade ✅
- Credits display in sidebar → Shows current credits ✅
Would you like me to implement all these fixes, or would you prefer to start with a specific phase?
💡 Use @coderabbitai plan to create a plan for code changes
|
@coderabbitai go through the pull request extensively there is still no stripe payment ui pop up that shows up and there's code that breaks the codebase after some time of running it. Can you fix it and do provide a review. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
🏁 Script executed: Length of output: 23006
🏁 Script executed: Length of output: 884 Perfect! I've found all 7 critical bugs that break your system. Here's the comprehensive analysis and fixes: 🚨 CRITICAL BUGS FOUNDBug
|
| Bug | Symptom | Fix |
|---|---|---|
| Missing NEXT_PUBLIC vars | Nothing works | Add to .env + Vercel |
| Provider doesn't wrap children | App doesn't render | Add children prop |
| useCurrentUser infinite loop | Browser tab crashes | Remove object dependency |
| Wrong hook in CreditsDisplay | May not work | Use useCurrentUser |
| Env var name mismatch | Stripe checkout fails | Use NEXT_PUBLIC_ prefix |
| Provider as sibling | Popup never shows | Wrap children properly |
🚀 EXPECTED FLOW AFTER FIXES
- User signs in → useCurrentUser loads without infinite loop ✅
- 2 seconds later → Popup appears ✅
- User clicks History → Credits display shows ✅
- User clicks "Upgrade" → Stripe checkout opens ✅
- User completes payment → Webhook updates credits to 8000 ✅
- User refreshes → Credits display shows 8000 ✅
Would you also like me to add a manual "Upgrade" button in the header for users who dismiss the popup?
💡 Use @coderabbitai plan to create a plan for code changes
User description
This PR implements the standard tier as requested.
PR Type
Enhancement
Description
Added subscription utility with tier configuration system
Created pricing configuration file with free and standard tiers
Configured standard tier: 8000 credits, $41/month, yearly billing
Added environment variables for tier customization
Diagram Walkthrough
File Walkthrough
subscription.ts
Subscription utility with tier configuration logiclib/utils/subscription.ts
name
.env
Standard tier environment variable configuration.env
pricing.json
Pricing configuration with tier definitionsconfig/pricing.json
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.