Skip to content

Conversation

@vinodM09
Copy link

@vinodM09 vinodM09 commented Dec 11, 2025

This PR addresses issue #251: the /pricing route was experiencing noticeable lag during scroll. Initial debugging reference: #164.

Summary

I was able to reproduce the lag on the pricing page. The animated shining border caused frequent paint and composite operations, which led to higher CPU usage and visible frame drops.
This PR replaces the animated border with a static one. The visual intent remains the same, while removing unnecessary rendering work.

Performance comparison

before:
before_os

after:
after_os

Closes #251

Summary by CodeRabbit

Release Notes

  • New Features

    • Redesigned pricing page with animated sections, enhanced features overview, and testimonial gallery.
    • Integrated analytics to better track user interactions and engagement.
    • Premium subscriber identification on testimonials.
    • Hash-based smooth scroll navigation for improved page exploration.
  • Performance

    • Font rendering optimization to prevent text display delays.
    • Lazy-loaded payment checkout for faster page loads.
  • Updates

    • Updated Next.js dependencies for improved stability and features.
    • Enhanced design system with new gradient styling options.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 11, 2025

@vinodM09 is attempting to deploy a commit to the AJEET PRATAP SINGH's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

📝 Walkthrough

Walkthrough

This PR refactors the pricing page into modular, data-driven components with performance optimizations and lazy-loading. It introduces comprehensive PostHog analytics integration across payment flows and landing pages, adds animation utilities, new UI components, and improves auth tracking with user creation timestamps. Additionally, it includes a Prisma seed script and minor dependency updates.

Changes

Cohort / File(s) Summary
Pricing Page Refactoring
apps/web/src/app/(main)/(landing)/pricing/page.tsx, apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx, apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx, apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx, apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
Converts monolithic pricing page into modular components: AnimatedFeaturesSection, AnimatedWhySection, PricingCardsSection, FreePlanCard, ProPlanCard, TestimonialsSection. Moves inline data (features, plan details, testimonials) to dedicated data module. Introduces Framer Motion animations with useInViewAnimation hooks for viewport-triggered transitions. Replaces default export from named Pricing to PricingPage function.
Design Tokens & Styling
apps/web/src/lib/design-tokens.ts, apps/web/tailwind.config.ts, apps/web/src/app/font-display-override.css, apps/web/src/app/globals.css
Adds purple.borderGradient design token with start/middle/end color stops. Extends Tailwind config with border-gradient background-image utility. Introduces font-display swap override for Geist and DM Mono to prevent text rendering blocking. Reformats globals.css selectors to multiline blocks.
Icon Components
apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
Exports four inline SVG icon components (TargetIcon, CheckIcon, TerminalIcon, CornerDownRightIcon) to eliminate lucide-react bundle impact. Each supports optional className prop; CheckIcon includes configurable strokeWidth.
Animation & Utility Hooks
apps/web/src/hooks/useInViewAnimation.ts, apps/web/src/components/utils/HashScrollHandler.tsx, apps/web/src/components/ui/HeaderStatic.tsx
Introduces useInViewAnimation hook using IntersectionObserver with threshold/triggerOnce/rootMargin options returning [ref, inView] tuple. Adds HashScrollHandler component detecting URL hash changes and smooth-scrolling to matching DOM elements. Creates HeaderStatic component with optional entrance animation and FlickeringGrid backdrop.
Payment Flow Components
apps/web/src/components/payment/LazyPaymentFlow.tsx, apps/web/src/components/ui/CustomButtonStatic.tsx
Introduces LazyPaymentFlow wrapper component that dynamically loads PaymentFlow on button click with ssr:false. Adds CustomButtonStatic server-compatible Link-based button with gradient background styling. Both extend payment/checkout UX with lazy-loading and static button variants.
Analytics Layer
apps/web/src/lib/analytics.ts, apps/web/src/hooks/useAnalytics.ts
Establishes centralized, type-safe analytics system via PostHog. Exports analytics object with generic track function, distinct-ID getter, and 10+ event-specific helpers (invest button, payment lifecycle, sign-in/up, link clicks). Includes privacy helpers: sanitizeAmount, truncateId, sanitizeCallbackUrl. Features development-time logging and error guards when PostHog unavailable.
PostHog Integration
apps/web/src/app/providers.tsx, apps/web/src/app/layout.tsx
Enhances PostHogProvider with extensive config: disables auto-pageview/session-recording, enables localStorage+cookie persistence, respects DNT. Adds PostHogAuthTracker component detecting sign-in/sign-up transitions via sessionStorage flags and emitting analytics events. Injects tracker into RootLayout inside SessionWrapper.
Landing Page Analytics
apps/web/src/components/landing-sections/Hero.tsx, apps/web/src/components/landing-sections/navbar.tsx, apps/web/src/components/landing-sections/footer.tsx, apps/web/src/components/landing-sections/CTA.tsx
Integrates useAnalytics hook across hero/navbar/footer/CTA sections. Adds onClick handlers tracking Get Started, Contribute, and social link interactions with location labels (hero, navbar, footer). Updates Hero headline to "Only platform you need to get into Open Source" with refined supporting text.
Payment & Auth Tracking
apps/web/src/components/payment/PaymentFlow.tsx, apps/web/src/components/login/SignInPage.tsx
Extends PaymentFlow with buttonLocation prop (default "payment_flow") and tracks invest button click, payment initiation/completion/failure, verification outcomes. Updates SignInPage to sanitize callback URL and emit trackSignInStarted with provider/callback context stored in sessionStorage for cross-session tracking.
Dashboard & Navigation
apps/web/src/components/dashboard/Sidebar.tsx
Injects analytics tracking on feature request, free-to-premium upgrade, navigation links, and profile actions. Updates text display for guest/unauthenticated states. Adds click handlers for premium-locked items with disabled styling and analytics before redirect-to-pricing.
Auth & Session Types
apps/web/src/lib/auth/config.ts, apps/web/src/types/next-auth.d.ts
Propagates user.createdAt from auth result through session callback and JWT callback to expose creation timestamp in both session and token objects. Extends Session and JWT NextAuth interfaces with optional createdAt string field.
Pitch Page Updates
apps/web/src/app/(main)/(landing)/pitch/page.tsx
Expands JSX heading tags across multiple lines; normalizes apostrophes to HTML entities (i'll, you don't). Adds buttonLocation="pitch_page" prop to PaymentFlow component usage in investment flow context.
Database & Build Config
apps/api/prisma/seed.ts, apps/api/package.json, apps/api/tsconfig.json
Adds Prisma seed script initializing test plan, users (one with premium subscription), payment records, and QueryCount entry with error handling. Includes "prisma": {"seed": "tsx prisma/seed.ts"} in package.json. Updates tsconfig.json with include/exclude to compile src/**/* while excluding prisma and node_modules.
Dependency Updates
apps/web/package.json, apps/docs/package.json
Bumps Next.js from 16.0.7→16.0.10 (web) and 14.2.15→14.2.35 (docs). Updates eslint-config-next to matching versions. No logic changes.
Content & Config
apps/web/src/utils/config.ts, apps/web/src/content/newsletters-premium, apps/web/src/components/ui/flickering-grid.tsx
Adds new project entry (id "11") to projectsOfTheWeek array with metadata. Updates newsletters-premium submodule pointer. Adds inline comment "Start false, animate only when visible" to useInView state in flickering-grid.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Possibly related PRs

Poem

🐰 Pricing pages spring to life with modular grace,
Analytics trails follow each user's pace,
Components dance, animations flow so sweet,
PaymentFlows lazy-load with every heartbeat,
Design tokens gleam with gradient borders bright!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Out of Scope Changes check ❓ Inconclusive The PR contains extensive changes beyond the core pricing page lag fix, including new pricing components, analytics tracking, auth token handling, and other landing page modifications that may exceed the scope of the original lag-fix objective in #251. Clarify whether all analytics integration, auth modifications, and peripheral landing page updates align with the #251 lag-fix objective or should be separated into distinct PRs.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'perf: reduce lag on pricing page' directly and accurately summarizes the main change in this PR, which addresses performance lag on the pricing route through optimization.
Linked Issues check ✅ Passed The PR addresses the primary objective of fixing the /pricing route lag by refactoring components, reducing animated effects, adding design tokens, and implementing optimizations. The additional optimizations to reduce LCP and unused JS/CSS align with performance improvement goals outlined in #251.
✨ Finishing touches
  • 📝 Generate docstrings

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.

@cla-assistant
Copy link

cla-assistant bot commented Dec 11, 2025

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/web/src/app/(main)/(landing)/pricing/page.tsx (2)

4-4: Remove unused ShineBorder import.

The ShineBorder component is no longer used after replacing it with the CSS gradient border. This import should be removed.

 import Footer from "@/components/landing-sections/footer";
 import Header from "@/components/ui/header";
-import { ShineBorder } from "@/components/ui/shine-borders";
 import { motion } from "framer-motion";

296-476: Overall assessment: Performance goal achieved, but design system compliance is broken.

The removal of the animated ShineBorder component and replacement with a static CSS gradient border should effectively reduce rendering work and address the lag issue. However, this change introduces design system violations that need to be fixed before merge:

  1. Hardcoded hex values (lines 301, 381): Colors must be moved to design tokens/Tailwind config
  2. Duplicate CSS classes (lines 301, 381): Extract the gradient border into a reusable component
  3. Unused import (line 4): Remove ShineBorder import

Address these issues to maintain code quality and design consistency.

♻️ Duplicate comments (1)
apps/web/src/app/(main)/(landing)/pricing/page.tsx (1)

381-381: Duplicate gradient border implementation—extract to reusable component or utility.

SecondaryPricingCard duplicates the exact same complex gradient border classes from PricingCard (line 301). Extract this into a reusable wrapper component or a Tailwind @apply utility class to reduce duplication and simplify maintenance.

This pairs with the design token extraction task (previous comment); once colors are moved to tokens, having a single shared border component will make future updates much easier.

Example refactor:

// Option 1: Reusable wrapper component
const GradientBorderCard = ({ children, className = "" }) => (
  <div className={`relative overflow-hidden rounded-3xl isolate before:absolute before:inset-0 ... ${className}`}>
    {children}
  </div>
);

// Usage:
<GradientBorderCard>
  {/* card content */}
</GradientBorderCard>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 050e439 and 375feae.

📒 Files selected for processing (2)
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx (2 hunks)
  • apps/web/tsconfig.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Remove unused imports

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Prefer functional components with TypeScript

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Organize imports in order: React → third-party → local components → utils → types

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use UPPER_SNAKE_CASE for constants

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use proper TypeScript types and avoid using `any` type

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use camelCase for functions and variables

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use dynamic imports for code splitting when appropriate

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Organize imports: react → third-party → local components → utils → types

Applied to files:

  • apps/web/tsconfig.json
🔇 Additional comments (1)
apps/web/tsconfig.json (1)

18-18: Verify the JSX runtime change is compatible with current React & Next.js versions.

The change from "preserve" to "react-jsx" is a good modernization (enables automatic JSX runtime), but ensure your React version is 17+ and Next.js is 13+, and that the build completes successfully with no regressions.

@vinodM09
Copy link
Author

okay, i'll fix it

@apsinghdev
Copy link
Owner

@vinodM09 nice work! pls fix the reviews then it'll be good to go.

@vinodM09 vinodM09 force-pushed the fix-pricing-page-lag branch from 375feae to a0fd41f Compare December 13, 2025 13:22
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 375feae and a0fd41f.

📒 Files selected for processing (4)
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx (5 hunks)
  • apps/web/src/lib/design-tokens.ts (1 hunks)
  • apps/web/tailwind.config.ts (1 hunks)
  • apps/web/tsconfig.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/lib/design-tokens.ts
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
**/src/{lib,utils}/**

📄 CodeRabbit inference engine (.cursorrules)

Use kebab-case or camelCase for utility file names

Files:

  • apps/web/src/lib/design-tokens.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/lib/design-tokens.ts
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/lib/design-tokens.ts
apps/web/src/{lib,utils}/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

Name files and folders using kebab-case or camelCase for utilities

Files:

  • apps/web/src/lib/design-tokens.ts
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : NEVER use hardcoded hex values (e.g., `#5519f7`) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)

Applied to files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : NEVER use hardcoded hex values (e.g., `#5519f7`) directly in components; ALWAYS reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/lib/design-tokens.ts
  • apps/web/tailwind.config.ts
  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Prefer functional components with TypeScript

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Remove unused imports

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Organize imports in order: React → third-party → local components → utils → types

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use dynamic imports for code splitting when appropriate

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use proper TypeScript types and avoid using `any` type

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use camelCase for functions and variables

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use UPPER_SNAKE_CASE for constants

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/web/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Organize imports: react → third-party → local components → utils → types

Applied to files:

  • apps/web/tsconfig.json
🔇 Additional comments (2)
apps/web/src/lib/design-tokens.ts (1)

36-40: LGTM! Well-structured design token for gradient border.

The new borderGradient token is properly structured, follows the existing pattern in the design tokens file, and includes a helpful comment describing its purpose for pricing cards. This aligns well with the PR objective of replacing the animated border with a static gradient.

apps/web/tailwind.config.ts (1)

13-21: LGTM! Properly configured Tailwind utility using design tokens.

The new border-gradient backgroundImage utility correctly references the design tokens from colors.brand.purple.borderGradient, avoiding hardcoded values. The gradient configuration (135deg angle with three color stops) is appropriate for creating the static border effect that replaces the animated ShineBorder component.

Based on learnings and coding guidelines about using design tokens rather than hardcoded values.

@vinodM09
Copy link
Author

I have addressed the review feedback by replacing all hardcoded hex values with design tokens. in addition, I removed blur effects from a few non critical areas to improve smoothness and performance while keeping the overall visual style unchanged and as intended. I also reverted some unintended changes from earlier commits, so the PR is now fully focused on the required updates. Everything should be aligned now. Please let me know if anything else needs adjustment. thanks

@apsinghdev
Copy link
Owner

@vinodM09 hey vinod, ive tested ur changes locally and i found the perf score is still 63. i acknowledge you've made an improvement, but can you pls look into it so that it can be improved more.

attaching some of my findings:

Screenshot 2025-12-15 at 4 17 29 PM Screenshot 2025-12-15 at 4 20 30 PM Screenshot 2025-12-15 at 4 20 53 PM

@vinodM09
Copy link
Author

vinodM09 commented Dec 16, 2025

@apsinghdev Thanks for the review and for sharing the performance results. I would like to share the testing process I followed and the results I am seeing locally, as there seems to be a difference in the reported scores.

For testing, I:

  • Ran a production build using 'npm run build' from the root directory
  • Started the app using 'npm start' from apps/web
  • Opened the application in an incognito tab

The same flow we use to validate deployment behavior. I tested the pricing page using this setup on both Chrome and Brave. In my case, the Lighthouse performance score is consistently above 97 to 98. The paint related issues are resolved as I mentioned previously in this PR, and the visible scroll lag that existed earlier is no longer present.

I have attached screenshots from my local tests for reference. While there are still some warnings related to unused JavaScript and CSS, those were already present earlier. Addressing them would require a broader optimization pass, and I am happy to work on that as a follow-up if needed.

To help align the results, could you please share the exact method you are using to measure performance? Also, are you still observing the visible scroll lag on your end? This will help me reproduce the same conditions and ensure we are evaluating the change consistently.

brave:
brave_lighthouse

chrome:
chrome_lighthouse

warnings:
warnings

thanks again for the review, and I am happy to iterate further if required.

@ketankauntia
Copy link
Contributor

Greate work @vinodM09 But, there is an issue rn. Localhost ≠ Real-world deployed websites.

On localhost: Zero network latency and JS already warm in memory.
In production: Real JS parsing & execution cost + cold start..

That’s why FCP is good (0.3s) but LCP is bad (4.2s) in prod.

Have a look here : https://chatgpt.com/share/6942c28d-d820-800e-9ae9-d4e1ca3fc487

You will require to reiterate. Just put it to cursor or antigravity's claude 4.5 thinking model and it will help you debug.

@vinodM09 vinodM09 force-pushed the fix-pricing-page-lag branch from 84f652d to 733c259 Compare December 19, 2025 18:41
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🧹 Nitpick comments (5)
apps/web/src/components/ui/CustomButtonStatic.tsx (2)

1-2: Consider adding React import for TypeScript type usage.

While the modern JSX runtime may handle React.ReactNode without an explicit import, it's clearer to import React when using its types:

+import React from "react";
 import { cn } from "@/lib/utils";
 import Link from "next/link";

21-29: Consider extracting shared button styles.

The styling is nearly identical to custom-button.tsx (lines 6-28). To reduce duplication and improve maintainability, consider extracting the shared className string to a constant or utility function that both components can use:

// in a shared location (e.g., apps/web/src/lib/button-styles.ts)
export const BUTTON_BASE_STYLES = [
  "flex gap-2 items-center justify-center px-5 py-3 rounded-[16px] relative",
  "border-x border-t-2 border-brand-purple",
  "bg-gradient-to-b from-[#5728f4] to-[#5100FF]", // replace with design tokens
  "[box-shadow:0px_-2px_0px_0px_#2c04b1_inset]", // replace with design tokens
  "hover:opacity-90 transition-opacity duration-100",
  "text-white font-medium",
].join(" ");

Then both components can reference this constant.

apps/web/src/hooks/useInViewAnimation.ts (1)

16-51: Consider using framer-motion's built-in useInView hook.

The custom implementation is correct, but framer-motion (already a project dependency) provides a built-in useInView hook with similar functionality. From apps/web/src/components/ui/number-ticker.tsx line 19, the codebase already uses framer-motion's useInView in other components.

Using the built-in hook would reduce maintenance burden and ensure consistency across the codebase.

🔎 Migration to framer-motion's useInView
-import { useEffect, useRef, useState } from 'react';
+import { useInView } from 'framer-motion';
+import { useRef } from 'react';

-interface UseInViewAnimationOptions {
-    threshold?: number;
-    triggerOnce?: boolean;
-    rootMargin?: string;
-}
-
-/**
- * Custom hook that detects when an element enters the viewport
- * Returns a ref to attach to the element and an inView boolean
- * 
- * @param options - Intersection Observer options
- * @returns [ref, inView] tuple
- */
-export function useInViewAnimation<T extends HTMLElement = HTMLDivElement>(
-    options: UseInViewAnimationOptions = {}
-) {
-    const { threshold = 0.1, triggerOnce = true, rootMargin = '0px' } = options;
-    const ref = useRef<T>(null);
-    const [inView, setInView] = useState(false);
-
-    useEffect(() => {
-        const element = ref.current;
-        if (!element) return;
-
-        const observer = new IntersectionObserver(
-            ([entry]) => {
-                if (entry.isIntersecting) {
-                    setInView(true);
-                    if (triggerOnce && element) {
-                        observer.unobserve(element);
-                    }
-                } else if (!triggerOnce) {
-                    setInView(false);
-                }
-            },
-            { threshold, rootMargin }
-        );
-
-        observer.observe(element);
-
-        return () => {
-            if (element) {
-                observer.unobserve(element);
-            }
-        };
-    }, [threshold, triggerOnce, rootMargin]);
-
-    return [ref, inView] as const;
-}
+export function useInViewAnimation<T extends HTMLElement = HTMLDivElement>(
+    options: { threshold?: number; triggerOnce?: boolean; rootMargin?: string } = {}
+) {
+    const { threshold = 0.1, triggerOnce = true, rootMargin = '0px' } = options;
+    const ref = useRef<T>(null);
+    const inView = useInView(ref, { 
+        once: triggerOnce, 
+        amount: threshold,
+        margin: rootMargin 
+    });
+    return [ref, inView] as const;
+}
apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (2)

322-326: Redundant ternary expression.

The ternary returns testimonial.content in both branches, making the condition unnecessary.

🔎 Proposed fix
-                            <div className="text-pretty">
-                                {typeof testimonial.content === "string"
-                                    ? testimonial.content
-                                    : testimonial.content}
-                            </div>
+                            <div className="text-pretty">
+                                {testimonial.content}
+                            </div>

The same pattern appears at lines 335-339 and 351-355.


246-255: Consider safer handling of optional premiumPlanId.

Using non-null assertion (premiumPlanId!) when planIdOk is true is logically safe, but a fallback makes the code more defensive.

🔎 Proposed fix
-                            <LazyPaymentFlow
-                                planId={planIdOk ? premiumPlanId! : ""}
+                            <LazyPaymentFlow
+                                planId={premiumPlanId ?? ""}

This achieves the same result without the non-null assertion, since an empty string is passed when premiumPlanId is undefined/null anyway.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0fd41f and 733c259.

📒 Files selected for processing (16)
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (1 hunks)
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (1 hunks)
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx (1 hunks)
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx (1 hunks)
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts (1 hunks)
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx (1 hunks)
  • apps/web/src/app/font-display-override.css (1 hunks)
  • apps/web/src/app/globals.css (1 hunks)
  • apps/web/src/components/payment/LazyPaymentFlow.tsx (1 hunks)
  • apps/web/src/components/ui/CustomButtonStatic.tsx (1 hunks)
  • apps/web/src/components/ui/HeaderStatic.tsx (1 hunks)
  • apps/web/src/components/ui/flickering-grid.tsx (1 hunks)
  • apps/web/src/components/utils/HashScrollHandler.tsx (1 hunks)
  • apps/web/src/hooks/useInViewAnimation.ts (1 hunks)
  • apps/web/src/lib/design-tokens.ts (1 hunks)
  • apps/web/tailwind.config.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/web/src/components/ui/flickering-grid.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/tailwind.config.ts
  • apps/web/src/lib/design-tokens.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
**/*[A-Z]*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Use PascalCase for component file names (e.g., UserProfile.tsx)

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
apps/web/src/components/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts,jsx,js}: Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale for section padding: p-4 (1rem) on mobile, p-[60px] on desktop
Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons
Use duration-100 (0.1s) for fast transitions, duration-300 (0.3s) for normal transitions, and duration-600 (0.6s) for slow transitions
Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine
Prefer functional components with TypeScript
Extract reusable logic into custom hooks
Prefer controlled components over uncontrolled
Include proper aria labels for accessibility
Ensure keyboard navigation works in interactive components
Maintain proper heading hierarchy in page components
Provide alt text for images
Use 'class:' instead of the ternary operator in class tags whenever possible
Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)
Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts

Files:

  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
apps/web/src/components/**/*.{tsx,ts}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts}: Use proper TypeScript types and avoid using any type
Use descriptive prop names and define prop types using TypeScript interfaces or types
Name components using PascalCase (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
🧠 Learnings (33)
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine

Applied to files:

  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Extract reusable logic into custom hooks

Applied to files:

  • apps/web/src/hooks/useInViewAnimation.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Extract reusable logic into custom hooks

Applied to files:

  • apps/web/src/hooks/useInViewAnimation.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Ensure keyboard navigation works in interactive components

Applied to files:

  • apps/web/src/components/utils/HashScrollHandler.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Ensure keyboard navigation works

Applied to files:

  • apps/web/src/components/utils/HashScrollHandler.tsx
📚 Learning: 2025-12-17T12:39:29.991Z
Learnt from: huamanraj
Repo: apsinghdev/opensox PR: 262
File: apps/web/src/components/checkout/CheckoutWrapper.tsx:5-5
Timestamp: 2025-12-17T12:39:29.991Z
Learning: In Next.js apps, avoid using redirect() from next/navigation inside Client Components during render. It should not be used in event handlers like onClick or onSubmit; for those cases, use useRouter().push() or router.replace() instead. This guidance applies to TSX files (React components) across the codebase; implement in client components to handle conditional redirects during render, and use router-based navigation in handlers.

Applied to files:

  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use animation durations: fast `duration-100` (0.1s), normal `duration-300` (0.3s), slow `duration-600` (0.6s)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Prefer functional components with TypeScript

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use `font-sans` for standard UI text (Geist Sans) and `font-mono` for code, technical content, or monospace needs (DM Mono)

Applied to files:

  • apps/web/src/app/globals.css
  • apps/web/src/app/font-display-override.css
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)

Applied to files:

  • apps/web/src/app/font-display-override.css
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Optimize images using next/image

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Remove unused imports

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use dynamic imports for code splitting when appropriate

Applied to files:

  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Maintain proper heading hierarchy in page components

Applied to files:

  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Maintain proper heading hierarchy

Applied to files:

  • apps/web/src/components/ui/HeaderStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Include proper aria labels for accessibility

Applied to files:

  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : NEVER use hardcoded hex values (e.g., `#5519f7`) directly in components; ALWAYS reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use semantic color names that describe purpose, not appearance

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use proper TypeScript types and avoid using `any` type

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*[Cc]omponent.{tsx,ts} : Keep components focused and single-responsibility

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Name components using PascalCase (e.g., UserProfile.tsx)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
🧬 Code graph analysis (9)
apps/web/src/hooks/useInViewAnimation.ts (1)
apps/web/src/components/ui/number-ticker.tsx (2)
  • NumberTicker (8-59)
  • latest (39-46)
apps/web/src/components/utils/HashScrollHandler.tsx (1)
apps/web/src/app/(main)/(landing)/pitch/page.tsx (1)
  • hash (20-31)
apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (4)
apps/web/src/app/(main)/(landing)/pricing/_components/types.ts (1)
  • Feature (1-6)
apps/web/src/hooks/useInViewAnimation.ts (1)
  • useInViewAnimation (16-51)
apps/web/src/components/ui/ActiveTag.tsx (1)
  • ActiveTag (8-23)
apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx (1)
  • CornerDownRightIcon (58-74)
apps/web/src/components/ui/CustomButtonStatic.tsx (3)
apps/web/src/lib/utils.ts (1)
  • cn (4-6)
apps/web/src/components/ui/button.tsx (2)
  • props (44-53)
  • ButtonProps (37-41)
apps/web/src/components/ui/custom-button.tsx (1)
  • children (7-29)
apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx (1)
apps/web/src/components/icons/icons.tsx (1)
  • Target (165-172)
apps/web/src/components/payment/LazyPaymentFlow.tsx (1)
apps/web/src/components/payment/PaymentFlow.tsx (3)
  • data (41-253)
  • PaymentFlowProps (12-20)
  • error (126-136)
apps/web/src/components/ui/HeaderStatic.tsx (2)
apps/web/src/components/ui/flickering-grid.tsx (1)
  • FlickeringGrid (23-199)
apps/web/src/components/ui/header.tsx (1)
  • title (7-44)
apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx (2)
apps/web/src/app/(main)/(landing)/pricing/_components/types.ts (1)
  • Feature (1-6)
apps/web/src/components/landing-sections/how-it-works.tsx (1)
  • HowItWorks (33-66)
apps/web/src/app/(main)/(landing)/pricing/page.tsx (4)
apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (3)
  • TestimonialsSection (304-362)
  • AnimatedWhySection (42-84)
  • PricingCardsSection (91-117)
apps/web/src/components/utils/HashScrollHandler.tsx (1)
  • HashScrollHandler (6-22)
apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (1)
  • AnimatedFeaturesSection (12-92)
apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx (2)
  • opensoxFeatures (3-50)
  • whySub (52-68)
🔇 Additional comments (12)
apps/web/src/components/ui/CustomButtonStatic.tsx (2)

4-8: LGTM!

The interface is well-defined with descriptive prop names and proper TypeScript types.


13-17: LGTM!

The function signature uses proper naming conventions and TypeScript types.

apps/web/src/components/ui/HeaderStatic.tsx (1)

17-31: Nice performance optimization with conditional animation.

The pattern of conditionally applying animation props based on the animate flag, combined with willChange hints, is excellent for reducing unnecessary animations on below-the-fold content. This directly supports the PR's performance goals.

apps/web/src/components/payment/LazyPaymentFlow.tsx (1)

26-48: Excellent lazy loading strategy for performance.

The pattern of showing a static button initially and only loading the PaymentFlow component on user interaction is a smart optimization that reduces the initial JavaScript bundle size and aligns well with the PR's performance goals.

apps/web/src/components/utils/HashScrollHandler.tsx (1)

6-22: Good extraction of reusable hash-scroll logic.

This component correctly extracts the hash-based scroll behavior that was previously inline in other pages (e.g., apps/web/src/app/(main)/(landing)/pitch/page.tsx lines 19-30). The implementation properly handles pathname changes and provides smooth scrolling to hash targets.

apps/web/src/app/(main)/(landing)/pricing/_components/types.ts (1)

1-6: LGTM - Clean type definition.

The Feature interface is well-structured with descriptive field names and proper TypeScript types. The flexible description field (string or ReactNode array) provides good API ergonomics for various content formats.

apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (1)

37-48: Nice staggered animation with performance hints.

The combination of staggered animation delays (index * 0.08) and willChange hints creates smooth, performant entrance animations. This approach aligns well with the PR's goal of reducing lag on the pricing page.

apps/web/src/app/font-display-override.css (1)

1-18: Remove unused font-display-override.css file.

The file is not imported in the layout or stylesheets, so the @font-face overrides never apply. Additionally, the current font setup uses Next.js's className and CSS variable approach (geistSans.className and dmMono.variable in layout.tsx), not direct font-family overrides. The identifiers in this file don't correspond to how fonts are actually loaded. Either delete this file or integrate font-display settings into the actual font configuration in layout.tsx using the display option.

apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx (1)

1-74: Well-structured inline SVG icons for bundle optimization.

The inline SVG approach eliminates the lucide-react dependency for these specific icons, which aligns with the PR's performance optimization goal. The icons properly use currentColor for inheritance and accept className for Tailwind styling.

apps/web/src/app/(main)/(landing)/pricing/page.tsx (1)

21-53: Good modular architecture with performance optimizations.

The refactored page structure addresses the PR objectives well:

  • Dynamic import for TestimonialsSection defers below-fold content
  • Font preload improves LCP
  • Data-driven composition reduces component complexity
  • planIdOk validation guards against undefined env variables

One minor note: Line 40 uses bg-[#151515]/20 - consider extracting this to a design token if it's a recurring pattern, though the /20 opacity modifier makes this less straightforward.

apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (2)

42-84: Good use of performance optimizations in animations.

The willChange: 'opacity, transform' style hints and staggered animation delays demonstrate awareness of rendering performance, which aligns with the PR's goal of reducing lag. The useInViewAnimation hook ensures animations only trigger when visible.


119-190: Good adoption of border-gradient design token for card borders.

The before:bg-border-gradient class (line 124) correctly uses the design token system for the gradient border effect, addressing the previous review feedback about hardcoded hex values in gradient borders.

@vinodM09
Copy link
Author

@apsinghdev ok so i reiterated the page and improved the performance of the page, i separated the page into server/client components to reduce the LCP, unused js and css, and network chaining, and doing these changes have made so much improvements (additionally no visual style is changed and also utilized the already existing components as much as we can do), i tested it localhost and also on build, and the results were great, also i have attached the findings,

on localhost:
local

on localhost with build (this eliminates the effect of browser extensions and we see deployment like conditions)
build

warnings: the current performance is already excellent, the remaining 93 KiB is mostly framework code that makes the application function properly, going below 50 KiB requires removing framer-motion, which is a significant trade-off (though i have reduced the use of framer-motion by altering the access techniques)
warnings_n

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (2)

237-242: Outdated discount deadline.

The "Discounted till 10 December" text references a past date. This should be updated or made dynamic.


97-97: Replace hardcoded background color with design token.

The hardcoded bg-[#151515]/20 violates the design system. Use a semantic token from the design system instead.

#!/bin/bash
# verify available background tokens in design system
rg -nP 'bg-surface|bg-background|bg-panel' apps/web/src/lib/design-tokens.ts apps/web/tailwind.config.ts -A2 -B2

Based on learnings, always reference colors from the design token system using Tailwind classes.

🧹 Nitpick comments (6)
apps/web/src/components/ui/CustomButtonStatic.tsx (2)

29-32: Replace inline styles with Tailwind utilities.

The inline style prop violates the coding guideline: "Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags."

Extend tailwind.config.ts to expose these design tokens as Tailwind utilities (e.g., bg-brand-purple-button-gradient and shadow-brand-purple-button), then use them in the className instead.

🔎 Suggested approach

First, extend apps/web/tailwind.config.ts:

// in the theme.extend section
backgroundImage: {
  'brand-purple-button-gradient': `linear-gradient(to bottom, ${colors.brand.purple.button.gradient.from}, ${colors.brand.purple.button.gradient.to})`
},
boxShadow: {
  'brand-purple-button': `0px -2px 0px 0px ${colors.brand.purple.button.shadow} inset`
}

Then update the component:

-        <Link
-            href={href}
-            className={cn(
-                "flex gap-2 items-center justify-center px-5 py-3 rounded-[16px] relative",
-                "border-x border-t-2 border-brand-purple",
-                "hover:opacity-90 transition-opacity duration-100",
-                "text-white font-medium",
-                className
-            )}
-            style={{
-                background: `linear-gradient(to bottom, ${colors.brand.purple.button.gradient.from}, ${colors.brand.purple.button.gradient.to})`,
-                boxShadow: `0px -2px 0px 0px ${colors.brand.purple.button.shadow} inset`,
-            }}
-        >
+        <Link
+            href={href}
+            className={cn(
+                "flex gap-2 items-center justify-center px-5 py-3 rounded-[16px] relative",
+                "bg-brand-purple-button-gradient shadow-brand-purple-button",
+                "border-x border-t-2 border-brand-purple",
+                "hover:opacity-90 transition-opacity duration-100",
+                "text-white font-medium",
+                className
+            )}
+        >

Then remove the unused colors import.

As per coding guidelines.


14-18: Consider adding an explicit return type.

Adding JSX.Element as the return type would improve type safety and align with the guideline to define types for const functions.

🔎 Suggested change
-export function CustomButtonStatic({
+export function CustomButtonStatic({
     children,
     className,
     href,
-}: CustomButtonStaticProps) {
+}: CustomButtonStaticProps): JSX.Element {
apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (4)

1-11: Consider reorganizing imports per coding guidelines.

The import order should follow: React → third-party → local components → utils → types. Currently, local icons are imported before Next.js components.

🔎 Suggested import order
 "use client";
 import { motion } from "framer-motion";
-import { TargetIcon, CheckIcon, TerminalIcon } from "./icons";
 import Image from "next/image";
 import Link from "next/link";
 import { useInViewAnimation } from "@/hooks/useInViewAnimation";
 import { HeaderStatic } from "@/components/ui/HeaderStatic";
 import { CustomButtonStatic } from "@/components/ui/CustomButtonStatic";
 import { ActiveTag } from "@/components/ui/ActiveTag";
 import { LazyPaymentFlow } from "@/components/payment/LazyPaymentFlow";
+import { TargetIcon, CheckIcon, TerminalIcon } from "./icons";
 import { freePlanCard, premiumPlanCard, testimonials } from "./data";

Based on coding guidelines, organize imports: React → third-party → local components → utils → types.


132-140: Reconsider image priority settings.

Setting priority and fetchPriority="high" for the logo may unnecessarily prioritize this resource. Reserve these for truly critical above-the-fold content.

🔎 Proposed change
                             <div className="w-12 h-12 relative">
                                 <Image
                                     src="/assets/logo_var2.svg"
                                     alt="Opensox logo"
                                     fill
-                                    priority
-                                    fetchPriority="high"
                                     className="object-cover size-full"
                                 />
                             </div>

211-221: Reconsider image priority settings.

Setting priority and fetchPriority="high" for the logo may unnecessarily prioritize this resource. Reserve these for truly critical above-the-fold content.

🔎 Proposed change
                             <div className="w-12 h-12 relative">
                                 <Image
                                     src="/assets/logo_var2.svg"
                                     alt="Opensox logo"
                                     fill
-                                    priority
-                                    fetchPriority="high"
                                     className="object-cover size-full"
                                 />
                             </div>

286-293: Fragile string comparison for feature detection.

Checking item === "Pro newsletter" is brittle and will break if the text changes. Consider adding an id or isActive property to feature data.

💡 Alternative approach

In your data file, add a property to identify active features:

// In data.tsx
{
  text: "Pro newsletter",
  isActive: true
}

Then use:

-                                        {item === "Pro newsletter" && <ActiveTag text="done" />}
+                                        {item.isActive && <ActiveTag text="done" />}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 733c259 and e0aa89c.

📒 Files selected for processing (6)
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (1 hunks)
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (1 hunks)
  • apps/web/src/app/globals.css (1 hunks)
  • apps/web/src/components/payment/LazyPaymentFlow.tsx (1 hunks)
  • apps/web/src/components/ui/CustomButtonStatic.tsx (1 hunks)
  • apps/web/src/components/ui/HeaderStatic.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/app/globals.css
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
**/*[A-Z]*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Use PascalCase for component file names (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
apps/web/src/components/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts,jsx,js}: Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale for section padding: p-4 (1rem) on mobile, p-[60px] on desktop
Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons
Use duration-100 (0.1s) for fast transitions, duration-300 (0.3s) for normal transitions, and duration-600 (0.6s) for slow transitions
Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine
Prefer functional components with TypeScript
Extract reusable logic into custom hooks
Prefer controlled components over uncontrolled
Include proper aria labels for accessibility
Ensure keyboard navigation works in interactive components
Maintain proper heading hierarchy in page components
Provide alt text for images
Use 'class:' instead of the ternary operator in class tags whenever possible
Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)
Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts

Files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
apps/web/src/components/**/*.{tsx,ts}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts}: Use proper TypeScript types and avoid using any type
Use descriptive prop names and define prop types using TypeScript interfaces or types
Name components using PascalCase (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
🧠 Learnings (27)
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*[Cc]omponent.{tsx,ts} : Keep components focused and single-responsibility

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Prefer functional components with TypeScript

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Maintain proper heading hierarchy in page components

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : NEVER use hardcoded hex values (e.g., `#5519f7`) directly in components; ALWAYS reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use semantic color names that describe purpose, not appearance

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use 'class:' instead of the ternary operator in class tags whenever possible

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-12-17T12:39:29.991Z
Learnt from: huamanraj
Repo: apsinghdev/opensox PR: 262
File: apps/web/src/components/checkout/CheckoutWrapper.tsx:5-5
Timestamp: 2025-12-17T12:39:29.991Z
Learning: In Next.js apps, avoid using redirect() from next/navigation inside Client Components during render. It should not be used in event handlers like onClick or onSubmit; for those cases, use useRouter().push() or router.replace() instead. This guidance applies to TSX files (React components) across the codebase; implement in client components to handle conditional redirects during render, and use router-based navigation in handlers.

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Extract reusable logic into custom hooks

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Always use lowercase when writing comments

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:38.559Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursor/rules/general_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:38.559Z
Learning: Applies to **/*.{js,jsx,ts,tsx,py,java,go,rb,php} : Always use lowercase when writing comments

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Avoid unnecessary comments; code should be self-documenting when possible

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use UPPER_SNAKE_CASE for constants

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use UPPER_SNAKE_CASE for constants

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use comments to explain 'why', not 'what'

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:38.559Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursor/rules/general_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:38.559Z
Learning: Applies to **/*.{js,jsx,ts,tsx,py,java,go,rb,php} : Avoid unnecessary comments; code should be self-documenting when possible

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use camelCase for functions and variables

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
🧬 Code graph analysis (1)
apps/web/src/components/ui/CustomButtonStatic.tsx (1)
apps/web/src/lib/utils.ts (1)
  • cn (4-6)
🔇 Additional comments (2)
apps/web/src/components/ui/CustomButtonStatic.tsx (1)

1-9: LGTM!

The imports are well-organized following the correct order, and the CustomButtonStaticProps interface uses proper TypeScript types with descriptive prop names.

apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (1)

42-84: Good animation performance practices.

The use of willChange: 'opacity, transform' and staggered delays optimizes rendering performance, aligning well with the PR's goal to reduce lag.

@vinodM09
Copy link
Author

i have resolved all the potential issues

@vinodM09 vinodM09 force-pushed the fix-pricing-page-lag branch from b4d9f57 to ea11f55 Compare December 30, 2025 22:06
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (1)
apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (1)

239-241: Update stale discount deadline.

The text "Discounted till 10 December" is outdated (today is December 30, 2025). This should be updated immediately or made configurable to prevent future staleness.

🔎 Suggested approaches

Option 1: Use an environment variable

const DISCOUNT_DEADLINE = process.env.NEXT_PUBLIC_DISCOUNT_DEADLINE || "Limited time";

Option 2: Move to a data constant

// In data.tsx
export const DISCOUNT_DEADLINE = "31 January 2025";

Then use it here:

<span className="...">
  Discounted till {DISCOUNT_DEADLINE}
</span>
🧹 Nitpick comments (11)
apps/api/prisma/seed.ts (4)

7-17: Use lowercase for comments.

Comments should start with lowercase per the coding guidelines. For example, "clear existing data..." instead of "Clear existing data...".

🔎 Suggested fix
 async function main() {
   console.log('🌱 Starting database seed...');
 
-  // Clear existing data (optional - only if you want fresh data each time)
-  // Uncomment if you want to reset data on each seed
+  // clear existing data (optional - only if you want fresh data each time)
+  // uncomment if you want to reset data on each seed
   // await prisma.payment.deleteMany();

56-84: Consider using upsert for consistency.

The manual check-then-update-or-create pattern can be simplified to use upsert like the other entities in this script. This would be more concise and consistent.

Also, the comment on line 56 should start with lowercase per coding guidelines.

🔎 Suggested refactor using upsert
-  // Create premium subscription for premium user
+  // create premium subscription for premium user
-  const existingSubscription = await prisma.subscription.findFirst({
-    where: {
-      userId: premiumUser.id,
-    },
-  });
-
-  const premiumSubscription = existingSubscription
-    ? await prisma.subscription.update({
-        where: { id: existingSubscription.id },
-        data: {
-          planId: testPlan.id,
-          status: 'active',
-          startDate: new Date(),
-          endDate: new Date(Date.now() + MILLIS_PER_YEAR), // 1 year from now
-          autoRenew: true,
-        },
-      })
-    : await prisma.subscription.create({
-        data: {
-          userId: premiumUser.id,
-          planId: testPlan.id,
-          status: 'active',
-          startDate: new Date(),
-          endDate: new Date(Date.now() + MILLIS_PER_YEAR), // 1 year from now
-          autoRenew: true,
-        },
-      });
-  console.log('✅ Created/updated premium subscription');
+  const premiumSubscription = await prisma.subscription.upsert({
+    where: {
+      userId_planId: {
+        userId: premiumUser.id,
+        planId: testPlan.id,
+      },
+    },
+    update: {
+      status: 'active',
+      startDate: new Date(),
+      endDate: new Date(Date.now() + MILLIS_PER_YEAR),
+      autoRenew: true,
+    },
+    create: {
+      userId: premiumUser.id,
+      planId: testPlan.id,
+      status: 'active',
+      startDate: new Date(),
+      endDate: new Date(Date.now() + MILLIS_PER_YEAR),
+      autoRenew: true,
+    },
+  });
+  console.log('✅ created/updated premium subscription');

Note: This assumes a composite unique constraint @@unique([userId, planId]) exists on the Subscription model. If not, you may need to add it or use a different unique field.


86-102: Lowercase comment.

Line 86 comment should start with lowercase: "create test payment" instead of "Create test payment".


104-117: Clarify initial QueryCount value.

A few observations:

  1. Line 104 comment should start with lowercase per coding guidelines.
  2. The initial value BigInt(2212) appears arbitrary. Consider using BigInt(0) or documenting why 2212 is the starting value.
  3. The error handling could be more specific—currently it logs "already exists or error" but doesn't distinguish between constraint violations and other errors.
🔎 Suggested improvements
-  // Create QueryCount if it doesn't exist
+  // create QueryCount if it doesn't exist
   try {
     await prisma.queryCount.upsert({
       where: { id: 1 },
       update: {},
       create: {
         id: 1,
-        total_queries: BigInt(2212),
+        total_queries: BigInt(0), // or document why 2212
       },
     });
-    console.log('✅ Created QueryCount');
+    console.log('✅ created QueryCount');
   } catch (error) {
-    console.log('⚠️  QueryCount already exists or error:', error);
+    if (error instanceof Error && 'code' in error && error.code === 'P2002') {
+      console.log('⚠️  queryCount already exists');
+    } else {
+      console.log('⚠️  error creating queryCount:', error);
+    }
   }
apps/web/src/lib/auth/config.ts (1)

36-39: Comment style: use lowercase.

The comments should start with lowercase per the coding guidelines.

As per coding guidelines, always use lowercase when writing comments in TypeScript files.

🔎 Suggested changes
-        // Store createdAt in user object for JWT callback
+        // store createdAt in user object for jwt callback
         if (authResult?.user?.createdAt) {
-      // Add createdAt from token to session
+      // add createdAt from token to session
       if (token.createdAt && session.user) {
-          // Store createdAt in token if available
+          // store createdAt in token if available
           if ((user as any).createdAt) {

Also applies to: 49-52, 70-73

apps/web/src/components/login/SignInPage.tsx (2)

37-52: Extract sessionStorage keys to constants.

The sessionStorage keys "posthog_sign_in_initiated" and "posthog_sign_in_provider" are hardcoded strings that appear to be used in multiple files (e.g., apps/web/src/app/providers.tsx based on the relevant snippets). This creates a maintenance risk if keys need to change.

🔎 Recommended approach

Create a shared constants file (e.g., apps/web/src/lib/analytics-constants.ts):

export const SIGN_IN_INITIATED_KEY = "posthog_sign_in_initiated";
export const SIGN_IN_PROVIDER_KEY = "posthog_sign_in_provider";

Then import and use these constants:

+import { SIGN_IN_INITIATED_KEY, SIGN_IN_PROVIDER_KEY } from "@/lib/analytics-constants";

 const handleSignIn = (provider: "google" | "github") => {
-    // Store only provider and boolean flag for post-callback tracking
-    // Do NOT store the full callback URL to avoid leaking tokens/PII
-    sessionStorage.setItem("posthog_sign_in_initiated", "true");
-    sessionStorage.setItem("posthog_sign_in_provider", provider);
+    // store only provider and boolean flag for post-callback tracking
+    // do not store the full callback url to avoid leaking tokens/pii
+    sessionStorage.setItem(SIGN_IN_INITIATED_KEY, "true");
+    sessionStorage.setItem(SIGN_IN_PROVIDER_KEY, provider);

Apply the same change in apps/web/src/app/providers.tsx.


38-39: Comment style: use lowercase.

Comments should use lowercase per the coding guidelines for TypeScript files.

As per coding guidelines:

🔎 Suggested changes
-    // Sanitize callback URL to prevent leaking sensitive query params or tokens
-    // Use centralized utility for consistent sanitization
+    // sanitize callback url to prevent leaking sensitive query params or tokens
+    // use centralized utility for consistent sanitization
     const sanitizedCallback = sanitizeCallbackUrl(safeCallbackUrl);

-    // Track sign-in attempt with sanitized callback (no query params or fragments)
+    // track sign-in attempt with sanitized callback (no query params or fragments)
     trackSignInStarted(provider, sanitizedCallback);

-    // Proceed with sign-in (use the full safe callback for actual redirect)
+    // proceed with sign-in (use the full safe callback for actual redirect)
     signIn(provider, { callbackUrl: safeCallbackUrl });

Also applies to: 45-46, 50-50

apps/web/src/app/(main)/(landing)/pitch/page.tsx (1)

45-45: Hardcoded hex values violate design token guidelines.

Multiple instances of hardcoded colors (#252525, #151515, #a472ea) should use design tokens. As per coding guidelines: "NEVER use hardcoded hex values directly in components; ALWAYS reference colors from the design token system using Tailwind classes."

Examples:

  • border-[#252525]border-dash-border or appropriate semantic token
  • bg-[#151515]/20bg-surface-primary/20 or equivalent
  • text-[#a472ea]text-brand-purple-light

Also applies to: 48-48, 78-79, 97-97, 128-128, 157-157, 161-161, 168-168, 172-172, 187-187, 213-213, 222-222, 231-231, 240-240, 258-258, 314-314, 383-383, 437-437, 473-473, 732-732, 748-748

apps/web/src/components/dashboard/Sidebar.tsx (1)

382-397: Consider extracting duplicate tracking logic.

The trackButtonClick call is duplicated in both onClick and onKeyDown handlers. Extract to a handler function to reduce duplication.

🔎 Suggested refactor
 {PREMIUM_ROUTES.map((route) => (
+  const handleLockedItemClick = () => {
+    trackButtonClick(`${route.label} (Locked)`, "sidebar");
+    router.push("/pricing");
+  };
+  return (
   <div
     key={route.path}
-    onClick={() => {
-      // Track locked premium feature click
-      trackButtonClick(`${route.label} (Locked)`, "sidebar");
-      router.push("/pricing");
-    }}
+    onClick={handleLockedItemClick}
     className="..."
     role="button"
     tabIndex={0}
     aria-label={`${route.label} - Upgrade to Pro`}
     onKeyDown={(e) => {
       if (e.key === "Enter" || e.key === " ") {
         e.preventDefault();
-        trackButtonClick(`${route.label} (Locked)`, "sidebar");
-        router.push("/pricing");
+        handleLockedItemClick();
       }
     }}
   >
apps/web/src/hooks/useAnalytics.ts (1)

119-126: Inconsistent return type with analytics.ts.

getDistinctId returns undefined here but null in apps/web/src/lib/analytics.ts (line 235-244). Consider aligning these for consistency.

🔎 Suggested fix
-    const getDistinctId = useCallback((): string | undefined => {
+    const getDistinctId = useCallback((): string | null => {
         try {
-            if (!posthog || !isReady) return undefined;
+            if (!posthog || !isReady) return null;
             return posthog.get_distinct_id();
         } catch {
-            return undefined;
+            return null;
         }
     }, [posthog, isReady]);
apps/web/tailwind.config.ts (1)

14-14: Use lowercase in comments.

🔎 Proposed fix
-        // Gradient used for card borders (pricing cards), sourced from brand design tokens
+        // gradient used for card borders (pricing cards), sourced from brand design tokens

Based on coding guidelines.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4d9f57 and ea11f55.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (37)
  • apps/api/package.json
  • apps/api/prisma/seed.ts
  • apps/api/tsconfig.json
  • apps/docs/package.json
  • apps/web/package.json
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
  • apps/web/src/app/font-display-override.css
  • apps/web/src/app/globals.css
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/components/ui/flickering-grid.tsx
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/content/newsletters-premium
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/hooks/useInViewAnimation.ts
  • apps/web/src/lib/analytics.ts
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/lib/design-tokens.ts
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/utils/config.ts
  • apps/web/tailwind.config.ts
✅ Files skipped from review due to trivial changes (3)
  • apps/web/src/content/newsletters-premium
  • apps/web/package.json
  • apps/web/src/app/globals.css
🚧 Files skipped from review as they are similar to previous changes (8)
  • apps/web/src/components/ui/flickering-grid.tsx
  • apps/web/src/components/ui/HeaderStatic.tsx
  • apps/web/src/components/payment/LazyPaymentFlow.tsx
  • apps/web/src/components/utils/HashScrollHandler.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx
  • apps/web/src/lib/design-tokens.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx
  • apps/web/src/hooks/useInViewAnimation.ts
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/tailwind.config.ts
  • apps/api/prisma/seed.ts
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
apps/web/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

apps/web/src/**/*.{ts,tsx}: Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts
NEVER use hardcoded hex values (e.g., #5519f7) directly in components; ALWAYS reference colors from the design token system using Tailwind classes
Use semantic color names that describe purpose, not appearance
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile p-4 (1rem) and desktop p-[60px]
Use appropriate border radius: small elements rounded-lg, medium rounded-xl, large rounded-2xl, buttons rounded-[16px]
Use animation durations: fast duration-100 (0.1s), normal duration-300 (0.3s), slow duration-600 (0.6s)

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,ts}: Prefer functional components with TypeScript and use proper TypeScript types, avoid any
Extract reusable logic into custom hooks
Use descriptive prop names and define prop types using TypeScript interfaces or types
Prefer controlled components over uncontrolled
Use zustand for global state (located in src/store/)
Use absolute imports from @/ prefix when available
Include proper aria labels for accessibility
Ensure keyboard navigation works
Maintain proper heading hierarchy
Provide alt text for images
Avoid unnecessary re-renders

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/tailwind.config.ts
  • apps/api/prisma/seed.ts
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Organize imports: react → third-party → local components → utils → types

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/tailwind.config.ts
  • apps/api/prisma/seed.ts
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*[A-Z]*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Use PascalCase for component file names (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/login/SignInPage.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx}: Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Memoize expensive computations

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/tailwind.config.ts
  • apps/api/prisma/seed.ts
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
apps/web/src/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursorrules)

Optimize images using next/image

apps/web/src/**/*.{tsx,ts}: Use Zustand for global state, located in src/store/
Use PascalCase for types and interfaces with descriptive names
Use dynamic imports for code splitting when appropriate
Optimize images using next/image
Memoize expensive computations
Define a type when defining const functions

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/*.{js,jsx,ts,tsx,py,java,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/general_rules.mdc)

**/*.{js,jsx,ts,tsx,py,java,go,rb,php}: Always use lowercase when writing comments
Avoid unnecessary comments; code should be self-documenting when possible
Use comments to explain 'why', not 'what'

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/tailwind.config.ts
  • apps/api/prisma/seed.ts
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
apps/web/src/components/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts,jsx,js}: Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes
Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)
Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)
Follow Tailwind's spacing scale for section padding: p-4 (1rem) on mobile, p-[60px] on desktop
Use rounded-lg (0.5rem) for small elements, rounded-xl (1rem) for medium elements, rounded-2xl (1.5rem) for large elements, and rounded-[16px] for buttons
Use duration-100 (0.1s) for fast transitions, duration-300 (0.3s) for normal transitions, and duration-600 (0.6s) for slow transitions
Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine
Prefer functional components with TypeScript
Extract reusable logic into custom hooks
Prefer controlled components over uncontrolled
Include proper aria labels for accessibility
Ensure keyboard navigation works in interactive components
Maintain proper heading hierarchy in page components
Provide alt text for images
Use 'class:' instead of the ternary operator in class tags whenever possible
Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)
Always follow the design system defined in apps/web/src/lib/design-tokens.ts and apps/web/tailwind.config.ts

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
apps/web/src/components/**/*.{tsx,ts}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/components/**/*.{tsx,ts}: Use proper TypeScript types and avoid using any type
Use descriptive prop names and define prop types using TypeScript interfaces or types
Name components using PascalCase (e.g., UserProfile.tsx)

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
apps/web/src/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

apps/web/src/**/*.{tsx,ts,jsx,js}: Organize imports in order: React → third-party → local components → utils → types
Use absolute imports from @/ prefix when available
Remove unused imports
Use UPPER_SNAKE_CASE for constants
Use camelCase for functions and variables
Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags
Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)
Use const with arrow functions instead of function declarations (e.g., 'const toggle = () =>')

Files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/types/next-auth.d.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/utils/config.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/lib/analytics.ts
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/lib/auth/config.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
**/src/{lib,utils}/**

📄 CodeRabbit inference engine (.cursorrules)

Use kebab-case or camelCase for utility file names

Files:

  • apps/web/src/utils/config.ts
  • apps/web/src/lib/analytics.ts
  • apps/web/src/lib/auth/config.ts
apps/web/src/{lib,utils}/**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (apps/web/.cursor/rules/frontend_rules.mdc)

Name files and folders using kebab-case or camelCase for utilities

Files:

  • apps/web/src/utils/config.ts
  • apps/web/src/lib/analytics.ts
  • apps/web/src/lib/auth/config.ts
🧠 Learnings (49)
📚 Learning: 2025-12-17T12:39:29.991Z
Learnt from: huamanraj
Repo: apsinghdev/opensox PR: 262
File: apps/web/src/components/checkout/CheckoutWrapper.tsx:5-5
Timestamp: 2025-12-17T12:39:29.991Z
Learning: In Next.js apps, avoid using redirect() from next/navigation inside Client Components during render. It should not be used in event handlers like onClick or onSubmit; for those cases, use useRouter().push() or router.replace() instead. This guidance applies to TSX files (React components) across the codebase; implement in client components to handle conditional redirects during render, and use router-based navigation in handlers.

Applied to files:

  • apps/web/src/components/landing-sections/CTA.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/dashboard/Sidebar.tsx
  • apps/web/src/app/providers.tsx
  • apps/web/src/components/payment/PaymentFlow.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/components/landing-sections/Hero.tsx
  • apps/web/src/components/landing-sections/footer.tsx
  • apps/web/src/components/login/SignInPage.tsx
  • apps/web/src/components/landing-sections/navbar.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use available custom animations: animate-accordion-down, animate-accordion-up, animate-scrollRight, animate-scrollLeft, animate-customspin, animate-spin-slow, animate-spin-slow-reverse, animate-marquee, animate-marquee-vertical, animate-shine

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Prefer functional components with TypeScript

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Name components using PascalCase (e.g., UserProfile.tsx)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Maintain proper heading hierarchy in page components

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*[Cc]omponent.{tsx,ts} : Keep components focused and single-responsibility

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : NEVER use hardcoded hex values (e.g., `#5519f7`) directly in components; ALWAYS reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/tailwind.config.ts
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use semantic color names from the design token system that describe purpose, not appearance (e.g., bg-brand-purple, bg-surface-primary, text-text-primary)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/tailwind.config.ts
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Never use hardcoded hex values directly in components; always reference colors from the design token system using Tailwind classes

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use semantic color names that describe purpose, not appearance

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Always follow the design system defined in `apps/web/src/lib/design-tokens.ts` and `apps/web/tailwind.config.ts`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/api/tsconfig.json
  • apps/web/tailwind.config.ts
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use 'class:' instead of the ternary operator in class tags whenever possible

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Avoid unnecessary comments; code should be self-documenting when possible

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{logging,middleware,utils}/*.{js,ts} : Use structured logging (JSON format) for easier parsing and analysis

Applied to files:

  • apps/web/src/lib/analytics.ts
  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use animation durations: fast `duration-100` (0.1s), normal `duration-300` (0.3s), slow `duration-600` (0.6s)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Implement accessibility features on interactive elements (e.g., tabindex='0', aria-label, onClick, onKeyDown)

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use appropriate border radius: small elements `rounded-lg`, medium `rounded-xl`, large `rounded-2xl`, buttons `rounded-[16px]`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/web/tailwind.config.ts
  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Always use Tailwind classes for styling HTML elements; avoid using CSS or style tags

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Follow Tailwind's spacing scale (0.25rem increments); for section padding use mobile `p-4` (1rem) and desktop `p-[60px]`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Extract reusable logic into custom hooks

Applied to files:

  • apps/web/src/hooks/useAnalytics.ts
  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Extract reusable logic into custom hooks

Applied to files:

  • apps/web/src/hooks/useAnalytics.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: This is a turborepo monorepo; respect package boundaries and use workspace dependencies properly

Applied to files:

  • apps/docs/package.json
📚 Learning: 2025-11-25T07:34:38.559Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursor/rules/general_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:38.559Z
Learning: Use workspace dependencies properly in turborepo monorepo

Applied to files:

  • apps/docs/package.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Organize imports: react → third-party → local components → utils → types

Applied to files:

  • apps/docs/package.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Organize imports in order: React → third-party → local components → utils → types

Applied to files:

  • apps/docs/package.json
  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Always use lowercase when writing comments

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:38.559Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursor/rules/general_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:38.559Z
Learning: Applies to **/*.{js,jsx,ts,tsx,py,java,go,rb,php} : Always use lowercase when writing comments

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use UPPER_SNAKE_CASE for constants

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use descriptive variable and function names; name event functions with a 'handle' prefix (e.g., handleClick, handleKeyDown)

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use UPPER_SNAKE_CASE for constants

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use comments to explain 'why', not 'what'

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:34:38.559Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursor/rules/general_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:38.559Z
Learning: Applies to **/*.{js,jsx,ts,tsx,py,java,go,rb,php} : Avoid unnecessary comments; code should be self-documenting when possible

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use camelCase for functions and variables

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/src/components/ui/CustomButtonStatic.tsx
  • apps/api/tsconfig.json
  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Maintain proper heading hierarchy

Applied to files:

  • apps/web/src/app/(main)/(landing)/pitch/page.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Remove unused imports

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/*.ts : Avoid `any` type; use `unknown` for truly dynamic data and narrow with type guards

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:58.984Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/api/.cursor/rules/backend_rules.mdc:0-0
Timestamp: 2025-11-25T07:34:58.984Z
Learning: Applies to apps/api/src/**/{routes,controllers,handlers,types}/*.ts : Define strict TypeScript interfaces for request/response bodies

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts,jsx,js} : Use absolute imports from `@/` prefix when available

Applied to files:

  • apps/api/tsconfig.json
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Use descriptive prop names and define prop types using TypeScript interfaces or types

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts} : Use proper TypeScript types and avoid using `any` type

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{tsx,ts} : Prefer functional components with TypeScript and use proper TypeScript types, avoid `any`

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to **/*.{ts,tsx} : Use PascalCase for types and interfaces with descriptive names

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/_components/types.ts
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Ensure keyboard navigation works in interactive components

Applied to files:

  • apps/web/src/components/landing-sections/navbar.tsx
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/**/*.{tsx,ts} : Use dynamic imports for code splitting when appropriate

Applied to files:

  • apps/web/src/app/(main)/(landing)/pricing/page.tsx
📚 Learning: 2025-11-25T07:34:30.473Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T07:34:30.473Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use `font-sans` for standard UI text (Geist Sans) and `font-mono` for code, technical content, or monospace needs (DM Mono)

Applied to files:

  • apps/web/src/app/font-display-override.css
📚 Learning: 2025-11-25T07:35:19.071Z
Learnt from: CR
Repo: apsinghdev/opensox PR: 0
File: apps/web/.cursor/rules/frontend_rules.mdc:0-0
Timestamp: 2025-11-25T07:35:19.071Z
Learning: Applies to apps/web/src/components/**/*.{tsx,ts,jsx,js} : Use font-sans for standard UI text (Geist Sans) and font-mono for code, technical content, or monospace needs (DM Mono)

Applied to files:

  • apps/web/src/app/font-display-override.css
🧬 Code graph analysis (17)
apps/web/src/components/landing-sections/CTA.tsx (3)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (1)
  • trackButtonClick (266-274)
apps/web/src/components/icons/icons.tsx (1)
  • Terminal (1-5)
apps/web/src/utils/config.ts (3)
apps/web/src/components/dashboard/ProjectsContainer.tsx (2)
  • p (112-161)
  • ProjectsContainer (54-179)
apps/web/src/app/(main)/dashboard/home/page.tsx (2)
  • setData (16-20)
  • useRenderProjects (10-26)
apps/web/src/utils/converter.ts (1)
  • item (144-156)
apps/web/src/app/layout.tsx (2)
apps/web/src/providers/trpc-provider.tsx (1)
  • TRPCProvider (11-53)
apps/web/src/app/SessionWrapper.tsx (1)
  • SessionWrapper (7-15)
apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (4)
apps/web/src/app/(main)/(landing)/pricing/_components/types.ts (1)
  • Feature (1-6)
apps/web/src/hooks/useInViewAnimation.ts (1)
  • useInViewAnimation (16-51)
apps/web/src/components/ui/ActiveTag.tsx (1)
  • ActiveTag (8-23)
apps/web/src/app/(main)/(landing)/pricing/_components/icons.tsx (1)
  • CornerDownRightIcon (58-74)
apps/web/src/components/dashboard/Sidebar.tsx (2)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (2)
  • trackLinkClick (354-366)
  • trackButtonClick (266-274)
apps/web/src/hooks/useAnalytics.ts (1)
apps/web/src/lib/analytics.ts (17)
  • AnalyticsEventName (13-28)
  • AnalyticsEventPropertiesMap (104-116)
  • ButtonClickedProperties (39-42)
  • track (207-229)
  • getDistinctId (235-244)
  • trackInvestButtonClick (251-261)
  • trackButtonClick (266-274)
  • trackPaymentInitiated (279-284)
  • sanitizeAmount (124-126)
  • trackPaymentCompleted (289-294)
  • truncateId (132-135)
  • trackPaymentFailed (299-305)
  • trackSubscriptionStarted (310-314)
  • trackSignInStarted (319-327)
  • trackSignInCompleted (332-340)
  • trackSignUpCompleted (345-349)
  • trackLinkClick (354-366)
apps/web/src/components/payment/PaymentFlow.tsx (2)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (5)
  • trackPaymentCompleted (289-294)
  • trackSubscriptionStarted (310-314)
  • trackPaymentFailed (299-305)
  • trackInvestButtonClick (251-261)
  • trackPaymentInitiated (279-284)
apps/web/src/lib/auth/config.ts (3)
apps/web/src/lib/trpc-server.ts (1)
  • serverTrpc (9-19)
apps/api/src/services/auth.service.ts (2)
  • handleGoogleAuth (28-58)
  • createOrUpdateOAuthAccount (65-148)
apps/api/src/routers/auth.ts (1)
  • authInput (23-68)
apps/web/src/app/(main)/(landing)/pitch/page.tsx (1)
apps/web/src/components/pitch/PitchInvest.tsx (2)
  • PitchInvest (16-47)
  • div (9-13)
apps/web/src/components/landing-sections/Hero.tsx (2)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (1)
  • trackButtonClick (266-274)
apps/api/package.json (1)
apps/api/src/prisma.ts (3)
  • account (61-62)
  • account (83-84)
  • update (31-35)
apps/web/src/components/landing-sections/footer.tsx (2)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (1)
  • trackLinkClick (354-366)
apps/web/src/app/(main)/(landing)/pricing/_components/types.ts (1)
apps/web/src/components/ui/features.tsx (2)
  • Features (95-329)
  • item (198-259)
apps/web/src/components/login/SignInPage.tsx (2)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (2)
  • sanitizeCallbackUrl (150-170)
  • trackSignInStarted (319-327)
apps/api/prisma/seed.ts (2)
apps/api/src/prisma.ts (6)
  • account (61-62)
  • account (83-84)
  • update (31-35)
  • connectDB (108-116)
  • create (26-30)
  • upsert (36-41)
apps/api/src/services/payment.service.ts (1)
  • createPaymentRecord (143-174)
apps/web/src/components/landing-sections/navbar.tsx (2)
apps/web/src/hooks/useAnalytics.ts (1)
  • useAnalytics (69-259)
apps/web/src/lib/analytics.ts (2)
  • trackButtonClick (266-274)
  • trackLinkClick (354-366)
apps/web/src/app/(main)/(landing)/pricing/page.tsx (5)
apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx (3)
  • TestimonialsSection (304-356)
  • AnimatedWhySection (42-84)
  • PricingCardsSection (91-117)
apps/web/src/components/utils/HashScrollHandler.tsx (1)
  • HashScrollHandler (6-22)
apps/web/src/components/ui/HeaderStatic.tsx (1)
  • HeaderStatic (17-61)
apps/web/src/app/(main)/(landing)/pricing/_components/AnimatedFeaturesSection.tsx (1)
  • AnimatedFeaturesSection (12-92)
apps/web/src/app/(main)/(landing)/pricing/_components/data.tsx (2)
  • opensoxFeatures (3-50)
  • whySub (52-68)

}: PricingCardsSectionProps) => {
return (
<div className="relative border-b border-border lg:pb-10">
<div className="flex flex-col gap-5 lg:gap-10 py-4 bg-[#151515]/20 backdrop-blur-xl h-full relative w-full overflow-hidden px-4 lg:px-10">
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace hardcoded background color with design token.

Line 97 uses bg-[#151515]/20 which violates the guideline to never use hardcoded hex values. This is the same color used in page.tsx line 40—both should reference a shared design token.

🔎 Proposed fix
-            <div className="flex flex-col gap-5 lg:gap-10 py-4 bg-[#151515]/20 backdrop-blur-xl h-full relative w-full overflow-hidden px-4 lg:px-10">
+            <div className="flex flex-col gap-5 lg:gap-10 py-4 bg-surface-secondary/20 backdrop-blur-xl h-full relative w-full overflow-hidden px-4 lg:px-10">

Coordinate with the fix for page.tsx line 40 to use the same token.

Based on coding guidelines.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/web/src/app/(main)/(landing)/pricing/_components/components.tsx around
line 97, replace the hardcoded Tailwind class bg-[#151515]/20 with the shared
design token used elsewhere (same token referenced from page.tsx line 40) so
both components use the identical token; update the JSX to use the token-based
class or CSS variable (consistent with your Tailwind/design-token conventions),
and if necessary coordinate with the change in page.tsx to ensure both files
import/reference the same token name.

<main className="w-full overflow-hidden flex flex-col items-center justify-center relative">
<HeaderStatic title="We are working on Opensox 2.0" animate={true} />

<div className="flex flex-col bg-[#151515]/20 backdrop-blur-xl relative w-full">
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace hardcoded background color with design token.

Line 40 uses bg-[#151515]/20 which violates the guideline to never use hardcoded hex values. Reference a color from the design token system instead.

🔎 Proposed fix

If #151515 represents a dark surface color, add it to design-tokens.ts or use an existing token:

-        <div className="flex flex-col bg-[#151515]/20 backdrop-blur-xl relative w-full">
+        <div className="flex flex-col bg-surface-secondary/20 backdrop-blur-xl relative w-full">

Or define a new token if this specific shade is intentional for the design system.

Based on coding guidelines.

📝 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.

Suggested change
<div className="flex flex-col bg-[#151515]/20 backdrop-blur-xl relative w-full">
<div className="flex flex-col bg-surface-secondary/20 backdrop-blur-xl relative w-full">
🤖 Prompt for AI Agents
In apps/web/src/app/(main)/(landing)/pricing/page.tsx around line 40, the
component uses a hardcoded hex background class `bg-[#151515]/20`; replace this
with a design token (e.g., an existing dark surface token or add a new one
representing that shade) and update the JSX to use the token-based class or CSS
variable instead; if the token does not exist, add it to the design-tokens.ts
(and to Tailwind/theme if needed) with the appropriate opacity handling, then
replace the hardcoded class with the token reference so the code complies with
the design-token guideline.

Comment on lines +91 to +92
Find suitabe OSS repos in seconds. learn the basics,
get the mentorship for OSS opportunities, GSoC, etc, and start making progress from today itself.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix typo and improve grammar in user-facing text.

Line 91 contains a typo: "suitabe" should be "suitable". Additionally, the phrasing "get the mentorship for OSS opportunities" could be improved for clarity.

🔎 Suggested fix
-          Find suitabe OSS repos in seconds. learn the basics,
-          get the mentorship for OSS opportunities, GSoC, etc, and start making progress from today itself.
+          Find suitable OSS repos in seconds. Learn the basics,
+          get mentorship for OSS opportunities like GSoC, and start making progress today.

Additional improvements:

  • Capitalized "Learn" (start of sentence after period)
  • Removed "the" before "mentorship" (more natural phrasing)
  • Changed "from today itself" to "today" (more natural English)
  • Added "like" before "GSoC" for better flow
📝 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.

Suggested change
Find suitabe OSS repos in seconds. learn the basics,
get the mentorship for OSS opportunities, GSoC, etc, and start making progress from today itself.
Find suitable OSS repos in seconds. Learn the basics,
get mentorship for OSS opportunities like GSoC, and start making progress today.
🤖 Prompt for AI Agents
In apps/web/src/components/landing-sections/Hero.tsx around lines 91 to 92, the
user-facing copy has a typo ("suitabe") and awkward phrasing; change "suitabe"
to "suitable", capitalize "Learn" after the period, remove the extra "the"
before "mentorship", add "like" before "GSoC" for flow, and replace "from today
itself" with "today" so the sentence reads naturally.

Comment on lines +319 to +327
export function trackSignInStarted(
provider: "google" | "github",
callbackUrl?: string
): void {
track("sign_in_started", {
provider,
callback_url: callbackUrl,
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing sanitization of callback_url.

trackSignInStarted passes callbackUrl directly without using sanitizeCallbackUrl. This could leak sensitive query parameters (tokens, codes) to analytics.

🔎 Suggested fix
 export function trackSignInStarted(
     provider: "google" | "github",
     callbackUrl?: string
 ): void {
     track("sign_in_started", {
         provider,
-        callback_url: callbackUrl,
+        callback_url: callbackUrl ? sanitizeCallbackUrl(callbackUrl) : undefined,
     });
 }
📝 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.

Suggested change
export function trackSignInStarted(
provider: "google" | "github",
callbackUrl?: string
): void {
track("sign_in_started", {
provider,
callback_url: callbackUrl,
});
}
export function trackSignInStarted(
provider: "google" | "github",
callbackUrl?: string
): void {
track("sign_in_started", {
provider,
callback_url: callbackUrl ? sanitizeCallbackUrl(callbackUrl) : undefined,
});
}
🤖 Prompt for AI Agents
In apps/web/src/lib/analytics.ts around lines 319 to 327, trackSignInStarted
currently forwards callbackUrl directly to analytics which can leak sensitive
query params; change it to call the existing sanitizeCallbackUrl(callbackUrl)
before passing to track so the callback_url value is scrubbed (or undefined if
sanitize returns null/undefined). Ensure you import or use the sanitize function
in this file and replace callbackUrl with the sanitized result in the track
payload.

Comment on lines +36 to +39
// Store createdAt in user object for JWT callback
if (authResult?.user?.createdAt) {
(user as any).createdAt = authResult.user.createdAt;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Improve type safety by extending the User interface.

The (user as any) type assertions bypass TypeScript's type checking. While this works at runtime, it reduces type safety and maintainability.

🔎 Recommended fix: Extend NextAuth User type

In apps/web/src/types/next-auth.d.ts, add a User interface extension:

 import "next-auth";

 declare module "next-auth" {
+  interface User {
+    createdAt?: string;
+  }
+
   interface Session {
     accessToken?: string;

Then update the auth config to use type-safe access:

-        // Store createdAt in user object for JWT callback
+        // store createdAt in user object for jwt callback
         if (authResult?.user?.createdAt) {
-          (user as any).createdAt = authResult.user.createdAt;
+          user.createdAt = authResult.user.createdAt;
         }
-          // Store createdAt in token if available
-          if ((user as any).createdAt) {
-            token.createdAt = new Date((user as any).createdAt).toISOString();
+          // store createdAt in token if available
+          if (user.createdAt) {
+            token.createdAt = new Date(user.createdAt).toISOString();
           }

Also applies to: 71-73

🤖 Prompt for AI Agents
In apps/web/src/lib/auth/config.ts around lines 36-39 and 71-73, remove the
(user as any) casts by extending NextAuth's User type so createdAt is part of
the User shape; add a declaration merging file at
apps/web/src/types/next-auth.d.ts that augments the next-auth User interface
with createdAt?: string | Date, ensure that file is included by TS (tsconfig
includes "src/types"), then update the auth config function signatures to use
the extended User type for the callback parameters and assign
authResult.user.createdAt directly to user.createdAt without any cast.

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.

[GENERAL] Experiencing lag on certain routes.

4 participants