Skip to content

Staging#37

Merged
izadoesdev merged 6 commits into
mainfrom
staging
Jul 27, 2025
Merged

Staging#37
izadoesdev merged 6 commits into
mainfrom
staging

Conversation

@izadoesdev

@izadoesdev izadoesdev commented Jul 27, 2025

Copy link
Copy Markdown
Member

Pull Request

Description

Please include a summary of the change and which issue is fixed. Also include relevant motivation and context.

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features

    • Added comprehensive analytics utilities for funnel and goal conversion data with referrer segmentation and flexible filtering.
    • Introduced a dedicated autocomplete API endpoint providing categorized analytics suggestions.
    • Added a new script for running the dashboard in development mode with environment variable support.
  • Enhancements

    • Funnel analytics components now support filtering and displaying data by selected referrer.
    • Improved typing and prop definitions across funnel analytics components for clearer data handling.
    • Enhanced accessibility and keyboard navigation for autocomplete dropdowns.
  • Refactor

    • Centralized analytics and filtering logic into reusable utility functions, simplifying router implementations.
    • Updated internal analytics processing to use utility modules and improved logging consistency.
    • Simplified type annotations and parameter naming in analytics query builders.
  • Chores

    • Updated development scripts to automatically load environment variables.
  • Removals

    • Removed the old autocomplete endpoint from the funnels API, replaced by a dedicated autocomplete router.

@vercel

vercel Bot commented Jul 27, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
dashboard (staging) ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 27, 2025 7:35pm

@coderabbitai

coderabbitai Bot commented Jul 27, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a major refactor and modularization of analytics processing in the codebase. Core logic for funnel and goal analytics is extracted into reusable utility modules, and new routers, including an autocomplete router, are added to the API. Type annotations are improved across query builder modules, and several UI components are refactored for better accessibility, clarity, and prop typing. Some scripts and configuration files are updated for improved development workflows.

Changes

Cohort Files Change Summary
Analytics Utility Extraction & Refactor packages/rpc/src/lib/analytics-utils.ts, packages/rpc/src/routers/funnels.ts, packages/rpc/src/routers/goals.ts Core analytics logic for funnels and goals is extracted into a new utility module. Routers now delegate analytics computation to these utilities, removing large blocks of inline SQL and manual aggregation.
New Routers & API Enhancements packages/rpc/src/root.ts, packages/rpc/src/routers/autocomplete.ts Adds an autocomplete router to the app router, providing categorized analytics suggestions. Integrates the new router into the main API.
Logger Addition packages/rpc/src/lib/logger.ts Introduces a Logtail logger for structured, batched logging using environment configuration.
Query Builder Type Simplification apps/api/src/query/builders/errors.ts, apps/api/src/query/builders/pages.ts, apps/api/src/query/builders/profiles.ts, apps/api/src/query/builders/sessions.ts, apps/api/src/query/builders/summary.ts, apps/api/src/query/builders/traffic.ts Type annotations for exported query builder constants are generalized, removing table-specific generics. Some function parameter names and types are updated for clarity and type safety.
Query Builder Internal Refactors apps/api/src/query/screen-resolution-to-device-type.ts, apps/api/src/query/simple-builder.ts, apps/api/src/query/types.ts Refactors for improved internal structure: helper functions are extracted, type annotations are tightened, and parameter property declarations are replaced with explicit assignments.
Dashboard Funnel UI Improvements apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/_components/page-header.tsx, apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx Refactors and enhances funnel analytics UI components: improves prop typing, adds referrer-filtered analytics display, increases accessibility, and simplifies component structure. Removes unused hooks and props.
Dashboard Autocomplete Hook Update apps/dashboard/hooks/use-funnels.ts The autocomplete data hook now queries a new, more general endpoint, aligning with backend changes.
Script and Config Updates apps/database/package.json, package.json Adds new dashboard development script, integrates dotenv for environment variable loading, and normalizes formatting.

Changes Table (Cohorts)

Cohort Files Change Summary
Analytics Utility Extraction & Refactor packages/rpc/src/lib/analytics-utils.ts,
packages/rpc/src/routers/funnels.ts,
packages/rpc/src/routers/goals.ts
Extracts analytics logic to a utility module; routers now delegate analytics processing. Removes inline SQL and manual aggregation from routers.
API Router Enhancements packages/rpc/src/root.ts,
packages/rpc/src/routers/autocomplete.ts
Adds autocomplete router and integrates it into the main API router. Provides categorized autocomplete suggestions from analytics data.
Logger Integration packages/rpc/src/lib/logger.ts Adds a Logtail logger for batched, structured logging.
Query Builder Type Simplification apps/api/src/query/builders/errors.ts,
apps/api/src/query/builders/pages.ts,
apps/api/src/query/builders/profiles.ts,
apps/api/src/query/builders/sessions.ts,
apps/api/src/query/builders/summary.ts,
apps/api/src/query/builders/traffic.ts
Generalizes type annotations for query builder constants and updates function parameter types/names for clarity.
Query Builder Internal Refactors apps/api/src/query/screen-resolution-to-device-type.ts,
apps/api/src/query/simple-builder.ts,
apps/api/src/query/types.ts
Refactors for better structure and type safety: extracts helpers, tightens types, and updates property assignments.
Dashboard Funnel UI Refactor apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/_components/page-header.tsx,
apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
Refactors and enhances funnel analytics UI: improves typing, adds referrer analytics, increases accessibility, removes unused code, and simplifies props.
Dashboard Autocomplete Hook Update apps/dashboard/hooks/use-funnels.ts Updates autocomplete hook to use new backend endpoint.
Script and Config Updates apps/database/package.json,
package.json
Adds dashboard dev script, uses dotenv for env loading, and normalizes formatting.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Dashboard
    participant API Router
    participant AnalyticsUtils
    participant Database

    Client->>Dashboard: Request funnel analytics (with filters/referrer)
    Dashboard->>API Router: Call getAnalytics/getAnalyticsByReferrer
    API Router->>AnalyticsUtils: processFunnelAnalytics/processFunnelAnalyticsByReferrer
    AnalyticsUtils->>Database: Query event/session data
    Database-->>AnalyticsUtils: Return raw analytics data
    AnalyticsUtils-->>API Router: Return processed analytics (conversion rates, dropoffs, etc.)
    API Router-->>Dashboard: Return analytics result
    Dashboard-->>Client: Render analytics UI (funnel, referrer breakdown, etc.)
Loading
sequenceDiagram
    participant Dashboard
    participant API Router
    participant AutocompleteRouter
    participant Database

    Dashboard->>API Router: Call autocomplete.get (websiteId, date range)
    API Router->>AutocompleteRouter: Fetch autocomplete suggestions
    AutocompleteRouter->>Database: Query distinct event fields
    Database-->>AutocompleteRouter: Return raw suggestion data
    AutocompleteRouter-->>API Router: Return categorized suggestions
    API Router-->>Dashboard: Return autocomplete data
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Staging #37: Shares identical changes simplifying type annotations in query builders and consistent renaming of parameters in custom SQL functions, directly related at the code level.

Poem

A rabbit hopped through fields of code,
Refactored funnels—what a load!
Utilities now neat and bright,
Routers trimmed for pure delight.
Autocomplete now quick and keen,
UI polished, fresh, and clean.
With every hop, the dashboard grows—
The analytics garden blooms and glows! 🥕✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a653f80 and 21bb70a.

📒 Files selected for processing (2)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx (7 hunks)
  • packages/rpc/src/lib/analytics-utils.ts (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch staging

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions

github-actions Bot commented Jul 27, 2025

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (6)
apps/api/src/query/screen-resolution-to-device-type.ts (1)

29-31: Remove unnecessary type check.

After screenResolution.split('x'), the array elements will always be strings, making this type check redundant.

-	if (typeof widthStr !== 'string' || typeof heightStr !== 'string') {
-		return null;
-	}
packages/rpc/src/routers/autocomplete.ts (2)

28-29: Consider extracting hardcoded event names as constants.

The excluded event names ('screen_view', 'page_exit', 'error', 'web_vitals', 'link_out') are hardcoded in the SQL query. Consider defining these as constants for better maintainability.

Add constants at the top of the file:

const EXCLUDED_EVENT_NAMES = ['screen_view', 'page_exit', 'error', 'web_vitals', 'link_out'] as const;

Then use them in the query by joining them as a string.


104-134: Optimize categorization for better performance.

The current implementation filters the results array multiple times. Consider using a single loop for better performance.

-const categorizeAutocompleteResults = (
-	results: Array<{ category: string; value: string }>
-) => ({
-	customEvents: results
-		.filter((r) => r.category === 'customEvents')
-		.map((r) => r.value),
-	pagePaths: results
-		.filter((r) => r.category === 'pagePaths')
-		.map((r) => r.value),
-	browsers: results
-		.filter((r) => r.category === 'browsers')
-		.map((r) => r.value),
-	operatingSystems: results
-		.filter((r) => r.category === 'operatingSystems')
-		.map((r) => r.value),
-	countries: results
-		.filter((r) => r.category === 'countries')
-		.map((r) => r.value),
-	deviceTypes: results
-		.filter((r) => r.category === 'deviceTypes')
-		.map((r) => r.value),
-	utmSources: results
-		.filter((r) => r.category === 'utmSources')
-		.map((r) => r.value),
-	utmMediums: results
-		.filter((r) => r.category === 'utmMediums')
-		.map((r) => r.value),
-	utmCampaigns: results
-		.filter((r) => r.category === 'utmCampaigns')
-		.map((r) => r.value),
-});
+const categorizeAutocompleteResults = (
+	results: Array<{ category: string; value: string }>
+) => {
+	const categorized = {
+		customEvents: [] as string[],
+		pagePaths: [] as string[],
+		browsers: [] as string[],
+		operatingSystems: [] as string[],
+		countries: [] as string[],
+		deviceTypes: [] as string[],
+		utmSources: [] as string[],
+		utmMediums: [] as string[],
+		utmCampaigns: [] as string[],
+	};
+
+	for (const { category, value } of results) {
+		if (category in categorized) {
+			categorized[category as keyof typeof categorized].push(value);
+		}
+	}
+
+	return categorized;
+};
apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx (1)

47-47: Use Array.from instead of Array constructor

Replace [...new Array(n)] with Array.from({length: n}) to avoid using the Array constructor.

-{[...new Array(3)].map((_, i) => (
+{Array.from({length: 3}).map((_, i) => (

Apply similar changes to lines 107 and 129.

Also applies to: 107-107, 129-129

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx (1)

107-107: Use Array.from instead of Array constructor

Replace [...new Array(n)] with Array.from({length: n}) to avoid using the Array constructor.

-{[...new Array(4)].map((_, i) => (
+{Array.from({length: 4}).map((_, i) => (

Apply similar change to line 129.

Also applies to: 129-129

packages/rpc/src/lib/analytics-utils.ts (1)

207-276: Consider documenting the placeholder time-based metrics.

The time-based metrics (avg_completion_time, avg_time_to_complete) are currently hardcoded to 0. Consider adding a TODO comment to indicate these are placeholders for future implementation.

 		return {
 			step_number: 1,
 			step_name: firstStep.name,
 			users: goalCompletions,
 			total_users: totalWebsiteUsers,
 			conversion_rate,
 			dropoffs: 0,
 			dropoff_rate: 0,
+			// TODO: Implement time-based analytics
 			avg_time_to_complete: 0,
 		},
 	];

 	return {
 		overall_conversion_rate: conversion_rate,
 		total_users_entered: totalWebsiteUsers,
 		total_users_completed: goalCompletions,
+		// TODO: Implement time-based analytics
 		avg_completion_time: 0,
 		avg_completion_time_formatted: '0s',
 		steps_analytics: analyticsResults,
 	};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 624efbe and a653f80.

📒 Files selected for processing (26)
  • apps/api/src/query/builders/errors.ts (1 hunks)
  • apps/api/src/query/builders/pages.ts (3 hunks)
  • apps/api/src/query/builders/profiles.ts (2 hunks)
  • apps/api/src/query/builders/sessions.ts (2 hunks)
  • apps/api/src/query/builders/summary.ts (2 hunks)
  • apps/api/src/query/builders/traffic.ts (1 hunks)
  • apps/api/src/query/screen-resolution-to-device-type.ts (2 hunks)
  • apps/api/src/query/simple-builder.ts (2 hunks)
  • apps/api/src/query/types.ts (1 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx (3 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx (9 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx (3 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx (1 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx (3 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx (2 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/page-header.tsx (0 hunks)
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx (6 hunks)
  • apps/dashboard/hooks/use-funnels.ts (1 hunks)
  • apps/database/package.json (1 hunks)
  • package.json (1 hunks)
  • packages/rpc/src/lib/analytics-utils.ts (1 hunks)
  • packages/rpc/src/lib/logger.ts (1 hunks)
  • packages/rpc/src/root.ts (2 hunks)
  • packages/rpc/src/routers/autocomplete.ts (1 hunks)
  • packages/rpc/src/routers/funnels.ts (10 hunks)
  • packages/rpc/src/routers/goals.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/page-header.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)

**/*.{ts,tsx}: Always ensure type-safety, don't use type: any unless needed, when creating APIs, responses, or components, create proper interfaces and make them in the shared types folders where it fits best, not in the same file
Never throw errors in server actions, use try catch and return the error to the client

**/*.{ts,tsx}: Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't return a value from a function with the return type 'void'.
Don't use the TypeScript directive @ts-ignore.
Don't use TypeScript enums.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use TypeScript namespaces.
Don't use non-null assertions with the ! postfix operator.
Don't use parameter properties in class constructors.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use either T[] or Array<T> consistently.
Initialize each enum member value explicitly.
Use export type for types.
Use import type for types.
Make sure all enum members are literal values.
Don't use TypeScript const enum.
Don't declare empty interfaces.
Don't let variables evolve into any type through reassignments.
Don't use the any type.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use implicit any type on variable declarations.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Use consistent accessibility modifiers on class properties and methods.
Use function types instead of object types with call signatures.
Don't use void type outside of generic or return types.

Files:

  • packages/rpc/src/root.ts
  • apps/api/src/query/types.ts
  • packages/rpc/src/routers/autocomplete.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx
  • apps/api/src/query/builders/traffic.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx
  • apps/api/src/query/builders/sessions.ts
  • apps/api/src/query/builders/errors.ts
  • packages/rpc/src/lib/logger.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx
  • apps/api/src/query/simple-builder.ts
  • apps/dashboard/hooks/use-funnels.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
  • apps/api/src/query/builders/pages.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
  • apps/api/src/query/builders/profiles.ts
  • packages/rpc/src/routers/goals.ts
  • packages/rpc/src/routers/funnels.ts
  • apps/api/src/query/builders/summary.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx
  • apps/api/src/query/screen-resolution-to-device-type.ts
  • packages/rpc/src/lib/analytics-utils.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)

**/*.{js,jsx,ts,tsx}: use console properly, like console.error, console.time, console.json, console.table, etc
Use Dayjs NEVER date-fns, and Tanstack query for hooks, NEVER SWR
Use ONLY Zod V4 from zod/v4 never zod 3 from zod
use json.stringify() when adding debugging

**/*.{js,jsx,ts,tsx}: Don't use consecutive spaces in regular expression literals.
Don't use the arguments object.
Don't use the comma operator.
Don't write functions that exceed a given Cognitive Complexity score.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possib...

Files:

  • packages/rpc/src/root.ts
  • apps/api/src/query/types.ts
  • packages/rpc/src/routers/autocomplete.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx
  • apps/api/src/query/builders/traffic.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx
  • apps/api/src/query/builders/sessions.ts
  • apps/api/src/query/builders/errors.ts
  • packages/rpc/src/lib/logger.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx
  • apps/api/src/query/simple-builder.ts
  • apps/dashboard/hooks/use-funnels.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
  • apps/api/src/query/builders/pages.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
  • apps/api/src/query/builders/profiles.ts
  • packages/rpc/src/routers/goals.ts
  • packages/rpc/src/routers/funnels.ts
  • apps/api/src/query/builders/summary.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx
  • apps/api/src/query/screen-resolution-to-device-type.ts
  • packages/rpc/src/lib/analytics-utils.ts
**/*.{html,ts,css}

📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file.html|file.ts|file.css> instead of webpack or esbuild

Files:

  • packages/rpc/src/root.ts
  • apps/api/src/query/types.ts
  • packages/rpc/src/routers/autocomplete.ts
  • apps/api/src/query/builders/traffic.ts
  • apps/api/src/query/builders/sessions.ts
  • apps/api/src/query/builders/errors.ts
  • packages/rpc/src/lib/logger.ts
  • apps/api/src/query/simple-builder.ts
  • apps/dashboard/hooks/use-funnels.ts
  • apps/api/src/query/builders/pages.ts
  • apps/api/src/query/builders/profiles.ts
  • packages/rpc/src/routers/goals.ts
  • packages/rpc/src/routers/funnels.ts
  • apps/api/src/query/builders/summary.ts
  • apps/api/src/query/screen-resolution-to-device-type.ts
  • packages/rpc/src/lib/analytics-utils.ts
package.json

📄 CodeRabbit Inference Engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

package.json: Use bun install instead of npm install, yarn install, or pnpm install
Use bun run <script> instead of npm run <script>, yarn run <script>, or pnpm run <script>

Files:

  • package.json
**/*.{jsx,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/01-MUST-DO.mdc)

**/*.{jsx,tsx}: Always use rounded, not rounded-xl or rounded-md, always rounded
Don't use lucide for icons, ONLY use phosphor icons, use width="duotone" for most, but for arrows use fill, for plus icons don't add width
ALWAYS use error boundaries properly
use Icon at the end of phosphor react icons, like CaretIcon not Caret
Almost NEVER use useEffect unless it's critical

**/*.{jsx,tsx}: Don't use accessKey attribute on any HTML element.
Don't set aria-hidden="true" on focusable elements.
Don't add ARIA roles, states, and properties to elements that don't support them.
Don't use distracting elements like <marquee> or <blink>.
Only use the scope prop on <th> elements.
Don't assign non-interactive ARIA roles to interactive HTML elements.
Make sure label elements have text content and are associated with an input.
Don't assign interactive ARIA roles to non-interactive HTML elements.
Don't assign tabIndex to non-interactive HTML elements.
Don't use positive integers for tabIndex property.
Don't include "image", "picture", or "photo" in img alt prop.
Don't use explicit role property that's the same as the implicit/default role.
Make static elements with click handlers use a valid role attribute.
Always include a title element for SVG elements.
Give all elements requiring alt text meaningful information for screen readers.
Make sure anchors have content that's accessible to screen readers.
Assign tabIndex to non-interactive HTML elements with aria-activedescendant.
Include all required ARIA attributes for elements with ARIA roles.
Make sure ARIA properties are valid for the element's supported roles.
Always include a type attribute for button elements.
Make elements with interactive roles and handlers focusable.
Give heading elements content that's accessible to screen readers (not hidden with aria-hidden).
Always include a lang attribute on the html element.
Always include a title attribute for iframe elements.
Accompany onClick with ...

Files:

  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx
apps/dashboard/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (apps/dashboard/.cursor/rules/ultracite.mdc)

apps/dashboard/**/*.{js,jsx,ts,tsx}: Don't use accessKey attribute on any HTML element.
Don't set aria-hidden="true" on focusable elements.
Don't add ARIA roles, states, and properties to elements that don't support them.
Don't use distracting elements like <marquee> or <blink>.
Only use the scope prop on <th> elements.
Don't assign non-interactive ARIA roles to interactive HTML elements.
Make sure label elements have text content and are associated with an input.
Don't assign interactive ARIA roles to non-interactive HTML elements.
Don't assign tabIndex to non-interactive HTML elements.
Don't use positive integers for tabIndex property.
Don't include "image", "picture", or "photo" in img alt prop.
Don't use explicit role property that's the same as the implicit/default role.
Make static elements with click handlers use a valid role attribute.
Always include a title element for SVG elements.
Give all elements requiring alt text meaningful information for screen readers.
Make sure anchors have content that's accessible to screen readers.
Assign tabIndex to non-interactive HTML elements with aria-activedescendant.
Include all required ARIA attributes for elements with ARIA roles.
Make sure ARIA properties are valid for the element's supported roles.
Always include a type attribute for button elements.
Make elements with interactive roles and handlers focusable.
Give heading elements content that's accessible to screen readers (not hidden with aria-hidden).
Always include a lang attribute on the html element.
Always include a title attribute for iframe elements.
Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress.
Accompany onMouseOver/onMouseOut with onFocus/onBlur.
Include caption tracks for audio and video elements.
Use semantic elements instead of role attributes in JSX.
Make sure all anchors are valid and navigable.
Ensure all ARIA properties (aria-*) are valid.
Use valid, non-abstract ARIA ...

Files:

  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx
  • apps/dashboard/hooks/use-funnels.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx
apps/dashboard/**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (apps/dashboard/.cursor/rules/ultracite.mdc)

apps/dashboard/**/*.{ts,tsx}: Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't return a value from a function that has a 'void' return type.
Don't use the TypeScript directive @ts-ignore.
Don't use TypeScript enums.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use TypeScript namespaces.
Don't use non-null assertions with the ! postfix operator.
Don't use parameter properties in class constructors.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use either T[] or Array<T> consistently.
Use consistent accessibility modifiers on class properties and methods.
Initialize each enum member value explicitly.
Use export type for types.
Use import type for types.
Make sure all enum members are literal values.
Use function types instead of object types with call signatures.
Don't use void type outside of generic or return types.
Don't use TypeScript const enum.
Don't declare empty interfaces.
Don't let variables evolve into any type through reassignments.
Don't use the any type.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use implicit any type on variable declarations.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.

Files:

  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx
  • apps/dashboard/hooks/use-funnels.ts
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx
apps/dashboard/**/*.{jsx,tsx}

📄 CodeRabbit Inference Engine (apps/dashboard/.cursor/rules/ultracite.mdc)

apps/dashboard/**/*.{jsx,tsx}: Don't use unnecessary fragments.
Don't pass children as props.
Don't forget key props in iterators and collection literals.
Don't destructure props inside JSX components in Solid projects.
Don't use configured elements.
Don't use <img> elements in Next.js projects.
Don't use dangerous JSX props.
Don't use both children and dangerouslySetInnerHTML props on the same element.
Don't use <head> elements in Next.js projects.
Use <>...</> instead of <Fragment>...</Fragment>.
Don't add extra closing tags for components without children.
Don't use Array index in keys.
Don't insert comments as text nodes.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't assign JSX properties multiple times.
Watch out for possible "wrong" semicolons inside JSX elements.

Files:

  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx
  • apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx
🧠 Learnings (20)
apps/database/package.json (12)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use dotenv; Bun automatically loads .env

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't hardcode sensitive data like API keys and tokens.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use the node: protocol for Node.js builtin modules.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't hardcode sensitive data like API keys and tokens.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to package.json : Use bun run <script> instead of npm run <script>, yarn run <script>, or pnpm run <script>

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use node:assert/strict over node:assert.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use the next/head module in pages/_document.js on Next.js projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't export empty modules that don't change anything.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't import next/document outside of pages/_document.jsx in Next.js projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't rename imports, exports, and destructured assignments to the same name.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use bun <file> instead of node <file> or ts-node <file>

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to package.json : Use bun install instead of npm install, yarn install, or pnpm install

packages/rpc/src/root.ts (4)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use import type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Prevent import cycles.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Declare regex literals at the top level.

apps/api/src/query/types.ts (18)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use ONLY Zod V4 from zod/v4 never zod 3 from zod

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use any or unknown as type constraints.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use import type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use function types instead of object types with call signatures.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use import type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Don't use the any type.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use any or unknown as type constraints.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Don't use user-defined types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use === and !==.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use === and !==.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use bitwise operators.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use the void operators (they're not familiar).

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't compare against -0.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use ternary operators when simpler alternatives exist.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use assignment operator shorthand where possible.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Remove redundant terms from logical expressions.

package.json (17)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to package.json : Use bun run <script> instead of npm run <script>, yarn run <script>, or pnpm run <script>

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't export empty modules that don't change anything.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure to use the "use strict" directive in script files.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use the node: protocol for Node.js builtin modules.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure builtins are correctly instantiated.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't rename imports, exports, and destructured assignments to the same name.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't hardcode sensitive data like API keys and tokens.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use node:assert/strict over node:assert.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use __dirname and __filename in the global scope.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use dotenv; Bun automatically loads .env

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use better-sqlite3; use bun:sqlite instead

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use bun <file> instead of node <file> or ts-node <file>

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Read the Bun API docs in node_modules/bun-types/docs/**.md for more information

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use Bun.$ instead of execa

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use specified modules when loaded by import or require.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-07-27T11:37:54.955Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use ioredis; use Bun.redis instead

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx (12)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use valid values for the autocomplete attribute on input elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't assign interactive ARIA roles to non-interactive HTML elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't assign non-interactive ARIA roles to interactive HTML elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make elements with interactive roles and handlers focusable.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use event handlers on non-interactive elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Always include a type attribute for button elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Use valid values for the autocomplete attribute on input elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Assign tabIndex to non-interactive HTML elements with aria-activedescendant.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use accessKey attribute on any HTML element.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Accompany onMouseOver/onMouseOut with onFocus/onBlur.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress.

apps/api/src/query/builders/traffic.ts (10)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use implicit any type on variable declarations.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx (21)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use function types instead of object types with call signatures.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use duplicate function parameter names.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use arrow functions instead of function expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Remove redundant terms from logical expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't reassign function parameters.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't have unused function parameters.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make static elements with click handlers use a valid role attribute.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use unnecessary fragments.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{jsx,tsx} : use Icon at the end of phosphor react icons, like CaretIcon not Caret

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{jsx,tsx} : Don't use lucide for icons, ONLY use phosphor icons, use width="duotone" for most, but for arrows use fill, for plus icons don't add width

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Make static elements with click handlers use a valid role attribute.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use event handlers on non-interactive elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Don't use event handlers on non-interactive elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make elements with interactive roles and handlers focusable.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Make elements with interactive roles and handlers focusable.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't pass children as props.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't destructure props inside JSX components in Solid projects.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx (15)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't export empty modules that don't change anything.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use Array index in keys.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use unnecessary fragments.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't destructure props inside JSX components in Solid projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't forget key props in iterators and collection literals.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use empty destructuring patterns.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use Array constructors.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't pass children as props.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't rename imports, exports, and destructured assignments to the same name.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use .flatMap() instead of map().flat() when possible.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure all React hooks are called from the top level of component functions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use import type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use unnecessary constructors.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use useless undefined.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Don't use Array index in keys.

apps/api/src/query/builders/sessions.ts (10)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use implicit any type on variable declarations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use any or unknown as type constraints.

apps/api/src/query/builders/errors.ts (10)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use implicit any type on variable declarations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use any or unknown as type constraints.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx (19)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Remove redundant terms from logical expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't have unused imports.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use unnecessary fragments.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't have unused function parameters.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use arrow functions instead of function expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't have unused labels.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use unnecessary callbacks with flatMap.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use duplicate function parameter names.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't declare empty interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{jsx,tsx} : use Icon at the end of phosphor react icons, like CaretIcon not Caret

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use Number properties instead of global ones.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{jsx,tsx} : Don't use lucide for icons, ONLY use phosphor icons, use width="duotone" for most, but for arrows use fill, for plus icons don't add width

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use literal numbers that lose precision.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use semantic elements instead of role attributes in JSX.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use dangerous JSX props.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure to use the digits argument with Number#toFixed().

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't destructure props inside JSX components in Solid projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Simplify data flow to eliminate prop drilling and callback hell.

apps/api/src/query/simple-builder.ts (2)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Don't use parameter properties in class constructors.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use parameter properties in class constructors.

apps/dashboard/hooks/use-funnels.ts (1)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use function types instead of object types with call signatures.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx (19)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use function types instead of object types with call signatures.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Remove redundant terms from logical expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use Array index in keys.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't forget key props in iterators and collection literals.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Don't use Array index in keys.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use for-of loops when you need the index to extract an item from the iterated array.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use Array constructors.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Don't forget key props in iterators and collection literals.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use sparse arrays (arrays with holes).

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use for...of statements instead of Array.forEach.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use at() instead of integer index access.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Use <>...</> instead of <Fragment>...</Fragment>.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use .flatMap() instead of map().flat() when possible.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Use while loops instead of for loops when you don't need initializer and update expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use Array constructors.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure to use the digits argument with Number#toFixed().

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Simplify data flow to eliminate prop drilling and callback hell.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use unnecessary fragments.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Handle complex data transformations independently of React. Keep these modules decoupled from React for improved modularity and testability.

apps/api/src/query/builders/pages.ts (10)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use implicit any type on variable declarations.

apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx (28)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use unnecessary fragments.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Remove redundant terms from logical expressions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use useless undefined.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't export empty modules that don't change anything.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Don't use unnecessary fragments.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't have unused function parameters.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't declare empty interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use empty destructuring patterns.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't use unnecessary callbacks with flatMap.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{jsx,tsx} : use Icon at the end of phosphor react icons, like CaretIcon not Caret

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure all React hooks are called from the top level of component functions.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{jsx,tsx} : Don't use lucide for icons, ONLY use phosphor icons, use width="duotone" for most, but for arrows use fill, for plus icons don't add width

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use <img> elements in Next.js projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make sure all dependencies are correctly specified in React hooks.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Decouple state management, data transformations, and API interactions from the React lifecycle.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use dangerous JSX props.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't destructure props inside JSX components in Solid projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Use <>...</> instead of <Fragment>...</Fragment>.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-27T11:36:04.592Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use Dayjs NEVER date-fns, and Tanstack query for hooks, NEVER SWR

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't forget key props in iterators and collection literals.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{jsx,tsx} : Don't use <head> elements in Next.js projects.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Make elements with interactive roles and handlers focusable.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Assign tabIndex to non-interactive HTML elements with aria-activedescendant.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Assign tabIndex to non-interactive HTML elements with aria-activedescendant.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Make elements with interactive roles and handlers focusable.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{js,jsx,ts,tsx} : Don't assign tabIndex to non-interactive HTML elements.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{jsx,tsx} : Don't assign tabIndex to non-interactive HTML elements.

apps/api/src/query/builders/profiles.ts (10)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use function types instead of object types with call signatures.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use function types instead of object types with call signatures.

apps/api/src/query/builders/summary.ts (1)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.942Z
Learning: Applies to **/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx (10)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use function types instead of object types with call signatures.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use primitive type aliases or misleading types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use as const instead of literal types and type annotations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use the any type.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.599Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use empty type parameters in type aliases and interfaces.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use either T[] or Array<T> consistently.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use user-defined types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Don't use implicit any type on variable declarations.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use import type for types.

apps/api/src/query/screen-resolution-to-device-type.ts (4)

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: apps/dashboard/.cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:39:48.600Z
Learning: Applies to apps/dashboard/**/*.{ts,tsx} : Use function types instead of object types with call signatures.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use export type for types.

Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-27T11:37:42.943Z
Learning: Applies to **/*.{ts,tsx} : Use function types instead of object types with call signatures.

🧬 Code Graph Analysis (6)
packages/rpc/src/root.ts (1)
packages/rpc/src/routers/autocomplete.ts (1)
  • autocompleteRouter (136-169)
apps/api/src/query/builders/traffic.ts (2)
apps/api/src/query/types.ts (1)
  • SimpleQueryConfig (28-54)
packages/db/src/clickhouse/schema.ts (1)
  • AnalyticsEvent (445-546)
apps/api/src/query/builders/errors.ts (1)
apps/api/src/query/types.ts (1)
  • SimpleQueryConfig (28-54)
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx (1)
apps/dashboard/app/(main)/websites/[id]/funnels/_components/index.ts (1)
  • FunnelFlow (6-6)
apps/api/src/query/simple-builder.ts (1)
apps/api/src/query/types.ts (2)
  • SimpleQueryConfig (28-54)
  • QueryRequest (56-68)
packages/rpc/src/routers/goals.ts (3)
packages/rpc/src/lib/analytics-utils.ts (3)
  • AnalyticsStep (4-9)
  • getTotalWebsiteUsers (62-83)
  • processGoalAnalytics (207-276)
packages/rpc/src/lib/logger.ts (1)
  • logger (5-9)
apps/dashboard/hooks/use-goals.ts (2)
  • useBulkGoalAnalytics (107-122)
  • useGoalAnalytics (90-105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (50)
apps/api/src/query/screen-resolution-to-device-type.ts (3)

10-14: Well-structured interface definition.

The Resolution interface is clean and appropriately typed for internal use. The inclusion of the aspect property alongside width and height improves code clarity in the device classification logic.


48-71: Well-structured device classification logic.

The function uses appropriate width and aspect ratio thresholds for device type classification. The hierarchical condition structure is logical and the fallback to 'unknown' ensures robust handling of edge cases.


82-83: Excellent refactoring that improves code clarity.

The main function is now much cleaner and easier to understand. The separation of parsing and classification logic into helper functions improves maintainability while preserving the same external interface.

apps/api/src/query/types.ts (1)

41-41: Improved type safety by replacing any with unknown.

This change aligns with TypeScript best practices and the coding guidelines. Using unknown instead of any provides better type safety by requiring explicit type checking before use.

apps/api/src/query/builders/traffic.ts (1)

4-4: Good type simplification as part of coordinated refactoring.

Removing the generic parameter makes the type annotation more accurate since the SimpleQueryConfig interface doesn't actually use generic constraints. This change is consistent with similar updates across other query builder files.

apps/api/src/query/builders/errors.ts (1)

4-4: Consistent type simplification aligns with broader refactoring.

This change mirrors the updates in other query builder files, removing unnecessary generic parameters from SimpleQueryConfig. The typing remains functionally equivalent while being more accurate to the actual interface definition.

apps/api/src/query/builders/pages.ts (3)

4-4: Consistent type annotation simplification.

This change aligns with the coordinated refactoring across all query builder files, removing unnecessary generic parameters while maintaining functional equivalence.


41-42: Good parameter naming and type safety improvements.

The underscore prefix correctly indicates these parameters are unused, and changing from any to unknown improves type safety. This follows TypeScript best practices and the project's coding guidelines.


101-102: Consistent parameter improvements match entry_pages function.

The naming convention and type safety improvements are consistently applied, maintaining code uniformity across the customSql functions.

apps/api/src/query/simple-builder.ts (2)

12-24: LGTM: Constructor refactor follows coding guidelines.

The refactor from parameter properties to explicit field declarations aligns with the coding guidelines and retrieved learnings. This improves code clarity by making the class structure more explicit.


149-151: Good formatting improvement.

The expansion of the single-line conditional to a block with braces improves code consistency and readability.

apps/api/src/query/builders/profiles.ts (2)

4-4: LGTM: Type annotation simplification improves consistency.

Removing the generic parameter <typeof Analytics.events> from SimpleQueryConfig makes the type more general and consistent across the codebase.


10-11: Excellent type safety improvement with parameter renaming.

The changes from any[]/any to unknown[]/unknown and prefixing parameter names with underscores (_filters, _granularity) improve type safety and clearly indicate these parameters are intentionally unused in the function implementations.

Also applies to: 226-227

apps/api/src/query/builders/sessions.ts (2)

4-4: LGTM: Consistent type annotation simplification.

The removal of the generic parameter maintains consistency with other builder files and simplifies the type declaration.


117-118: Good type safety enhancement.

Changing parameter types from any[]/any to unknown[]/unknown and using underscore prefixes for unused parameters follows best practices for type safety and parameter naming.

apps/api/src/query/builders/summary.ts (2)

4-4: LGTM: Type annotation follows established pattern.

The type simplification is consistent with changes in other builder files, improving overall codebase consistency.


117-118: Good type safety improvement with preserved functionality.

The parameter type changes from specific types (Filter[], TimeUnit) to unknown[]/unknown with underscore prefixes improve type consistency across builder files. The granularity logic on line 124 continues to work correctly, demonstrating that the calling code maintains proper type handling.

Also applies to: 124-124

packages/rpc/src/root.ts (1)

1-1: LGTM! Clean integration of autocomplete router

The new autocomplete router is properly imported and integrated into the appRouter following the established pattern. The change is consistent with the existing code structure.

Also applies to: 15-15

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-card.tsx (2)

33-69: LGTM! Good refactoring for improved readability

The extraction of getStepIcon and getStepTooltipText helper functions improves code organization by removing inline conditional logic. The functions handle different step types appropriately and follow the established icon usage patterns.


81-83: Clean formatting improvement

The reformatted early return condition is more readable while maintaining the same logic.

apps/dashboard/hooks/use-funnels.ts (1)

346-346: LGTM! Endpoint migration looks correct.

The update from trpc.funnels.getAutocomplete to trpc.autocomplete.get correctly reflects the backend refactoring that moves autocomplete functionality to a dedicated router.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-components.tsx (1)

99-112: Excellent accessibility improvements!

The changes properly implement:

  • Semantic HTML by using button elements for interactive items
  • Keyboard navigation with Enter/Space key handling
  • Better key prop using suggestion string instead of array index
  • Correct type="button" to prevent form submission

These changes align with the coding guidelines for accessibility and best practices.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnels-list.tsx (2)

3-3: Good cleanup - removed unused import.

Removing CardContent from imports follows best practices for keeping imports clean.


33-34: Clean array initialization improvement.

Using new Array(3).fill(null) is cleaner than the spread operator approach, and renaming i to index improves readability. For static loading skeletons, using index as key is acceptable.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-flow.tsx (2)

3-3: Good cleanup - removed unused icon imports.

Keeping only the required TargetIcon import follows best practices.


20-20: Clean refactoring improvements.

  • Removed unused formatCompletionTime prop from interface and component
  • Used .at() method for array access as per coding guidelines

These changes simplify the component interface and follow modern JavaScript practices.

Also applies to: 30-31

packages/rpc/src/routers/autocomplete.ts (3)

1-6: Imports look good!

Correctly using zod/v4 as specified in coding guidelines and proper module imports.


33-36: Verify URL path extraction logic.

The path extraction logic assumes URLs start with 'http' and uses position 9 to find the path. This might not work correctly for all URL formats (e.g., 'https://' vs 'http://', URLs with ports).

Consider using URL parsing for more robust path extraction:

-CASE 
-	WHEN path LIKE 'http%' THEN 
-		substring(path, position(path, '/', 9))
-	ELSE path
-END as value
+CASE 
+	WHEN path LIKE 'http%' THEN 
+		extractURLParameter(path, 'path')
+	ELSE path
+END as value

Or handle this in the application layer using the URL constructor.


136-169: Implementation looks solid overall!

The router implementation follows best practices:

  • Proper authorization checks
  • Parameterized queries preventing SQL injection
  • Appropriate error handling and logging
  • Clean separation of concerns
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics-by-referrer.tsx (3)

26-29: Good type safety improvement!

The explicit typing of the data prop removes the use of any and provides proper type information, aligning with TypeScript best practices.


53-58: Excellent removal of any type!

The explicit typing of the grouped Map values with FunnelAnalyticsByReferrerResult['referrer_parsed'] improves type safety and code maintainability.


163-163: Good practice: Let TypeScript infer the type

Removing the explicit any type annotation on the option parameter allows TypeScript to properly infer the type from the array, which is the recommended approach.

packages/rpc/src/routers/goals.ts (3)

5-10: Great refactoring: Analytics logic extraction

Excellent work extracting analytics processing logic into reusable utility functions. This improves code maintainability and follows the DRY principle.


191-198: Good type safety with explicit typing

The explicit AnalyticsStep[] typing and structured step object improve type safety and code clarity.


271-291: Excellent error handling implementation

The try-catch block with proper logging provides robust error handling. The error response structure ensures clients receive meaningful error information while logging details server-side.

apps/dashboard/app/(main)/websites/[id]/funnels/page.tsx (2)

6-6: Good practice: Removing unnecessary useEffect

Excellent removal of useEffect from imports, following the guideline to avoid useEffect unless critical.


323-323: Good accessibility improvement

Adding role="tablist" improves screen reader accessibility for the analytics container.

packages/rpc/src/routers/funnels.ts (3)

5-10: Excellent refactoring: Centralized analytics processing

Great work extracting funnel analytics logic into reusable utilities. This significantly reduces code duplication and improves maintainability.


93-96: Consistent structured logging implementation

Excellent adoption of the centralized logger with structured logging. The error context includes all relevant information for debugging.

Also applies to: 139-143, 176-181, 185-189


353-360: Clean analytics steps transformation

The mapping to AnalyticsStep[] with explicit typing and proper structure improves type safety and code clarity.

apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx (4)

11-11: Good optimization: Using useMemo for derived state

Excellent choice using useMemo instead of useState for derived data, avoiding unnecessary re-computations.


16-26: Well-structured interface definition

The ReferrerAnalytics interface is properly typed without using any types, following TypeScript best practices.


45-96: Complex but well-implemented data derivation

The memoized computation properly handles the conditional display logic for referrer-specific data. Good use of nullish checks and proper typing throughout.


219-219: Correct usage of toFixed

Good practice using toFixed(1) with the proper digits argument as required by the coding guidelines.

Also applies to: 237-237

packages/rpc/src/lib/analytics-utils.ts (6)

1-61: LGTM! Well-structured interfaces for analytics data models.

The interfaces are properly typed and provide a clear structure for analytics data flow throughout the module.


62-83: LGTM! Clean implementation for fetching total website users.

Good use of parameterized queries and null-safe return value.


85-126: LGTM! Secure query building with proper parameterization.

The query builders handle both PAGE_VIEW and EVENT types appropriately, with good support for partial URL matching.


128-205: LGTM! Efficient session event processing with correct sequential logic.

The implementation properly tracks users through sequential funnel steps using efficient data structures.


486-603: LGTM! Comprehensive funnel analytics processing with proper error handling.

The implementation correctly calculates conversion rates, dropoff rates, and identifies the biggest dropoff step. Good use of error handling in the referrer parsing logic.


605-841: LGTM! Well-implemented referrer analytics with proper domain grouping.

The implementation effectively groups and analyzes funnel performance by traffic source, with appropriate handling of direct traffic and domain-based aggregation.

Comment on lines 228 to 229
{displayData.avg_completion_time}
</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use formatted time value for display

The code displays the numeric avg_completion_time value directly. Consider using avg_completion_time_formatted for proper time display.

-{displayData.avg_completion_time}
+{displayData.avg_completion_time_formatted}
📝 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
{displayData.avg_completion_time}
</div>
{displayData.avg_completion_time_formatted}
</div>
🤖 Prompt for AI Agents
In
apps/dashboard/app/(main)/websites/[id]/funnels/_components/funnel-analytics.tsx
around lines 228 to 229, replace the direct display of the numeric
avg_completion_time with the formatted time value avg_completion_time_formatted
to ensure the time is shown properly to users.

"private": true,
"scripts": {
"dev": "next dev -p 3004",
"dev": "dotenv -- next dev -p 3004",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unnecessary dotenv prefix - Bun automatically loads .env files

According to the coding guidelines, Bun automatically loads .env files, making the dotenv -- prefix unnecessary. This script should simply be "next dev -p 3004".

-    "dev": "dotenv -- next dev -p 3004",
+    "dev": "next dev -p 3004",
📝 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
"dev": "dotenv -- next dev -p 3004",
"dev": "next dev -p 3004",
🤖 Prompt for AI Agents
In apps/database/package.json at line 6, remove the unnecessary "dotenv --"
prefix from the "dev" script since Bun automatically loads .env files. Change
the script value from "dotenv -- next dev -p 3004" to just "next dev -p 3004".

Comment thread package.json
"db:deploy": "dotenv -- turbo run db:deploy",
"email:dev": "cd packages/email && bun run dev",
"sdk:build": "cd packages/sdk && bun run build",
"dashboard:dev": "dotenv -- cd apps/dashboard; bun run dev"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unnecessary dotenv prefix - Bun automatically loads .env files

The new dashboard:dev script uses dotenv -- which is unnecessary since Bun automatically loads .env files. This script should be simplified.

-    "dashboard:dev": "dotenv -- cd apps/dashboard; bun run dev"
+    "dashboard:dev": "cd apps/dashboard; bun run dev"

Note: This pattern appears in multiple scripts throughout the file, suggesting a broader refactoring opportunity to remove dotenv usage project-wide.

📝 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
"dashboard:dev": "dotenv -- cd apps/dashboard; bun run dev"
"dashboard:dev": "cd apps/dashboard; bun run dev"
🤖 Prompt for AI Agents
In package.json at line 20, remove the unnecessary "dotenv --" prefix from the
"dashboard:dev" script since Bun automatically loads .env files. Simplify the
script to just run "cd apps/dashboard; bun run dev". Also, review other scripts
in the file using "dotenv --" and remove that prefix project-wide for
consistency.

Comment thread packages/rpc/src/lib/analytics-utils.ts
Comment on lines +3 to +4
const token = process.env.LOGTAIL_SOURCE_TOKEN as string;
const endpoint = process.env.LOGTAIL_ENDPOINT as string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add proper environment variable validation

Using type assertions without validation can cause runtime errors if the environment variables are undefined. Consider adding proper validation or fallback values.

-const token = process.env.LOGTAIL_SOURCE_TOKEN as string;
-const endpoint = process.env.LOGTAIL_ENDPOINT as string;
+const token = process.env.LOGTAIL_SOURCE_TOKEN;
+const endpoint = process.env.LOGTAIL_ENDPOINT;
+
+if (!token || !endpoint) {
+	throw new Error('LOGTAIL_SOURCE_TOKEN and LOGTAIL_ENDPOINT must be defined');
+}
📝 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
const token = process.env.LOGTAIL_SOURCE_TOKEN as string;
const endpoint = process.env.LOGTAIL_ENDPOINT as string;
// packages/rpc/src/lib/logger.ts
import { Logtail } from '@logtail/node';
const token = process.env.LOGTAIL_SOURCE_TOKEN;
const endpoint = process.env.LOGTAIL_ENDPOINT;
if (!token || !endpoint) {
throw new Error('LOGTAIL_SOURCE_TOKEN and LOGTAIL_ENDPOINT must be defined');
}
const logger = new Logtail(token, {
endpoint,
batchSize: 10,
batchInterval: 3000,
});
export { logger };
🤖 Prompt for AI Agents
In packages/rpc/src/lib/logger.ts around lines 3 to 4, the environment variables
LOGTAIL_SOURCE_TOKEN and LOGTAIL_ENDPOINT are accessed using type assertions
without validation, which can lead to runtime errors if they are undefined. Add
checks to verify these environment variables are defined before using them, and
provide fallback values or throw descriptive errors if they are missing to
ensure safe usage.

@izadoesdev
izadoesdev merged commit 597e27f into main Jul 27, 2025
4 of 7 checks passed
};

const escapeSqlWildcards = (value: string): string => {
return value.replace(/[%_]/g, '\\$&');

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI 12 months ago

To fix the problem, the escapeSqlWildcards function should be updated to also escape backslashes in the input string. The correct order is to first escape all backslashes (replace each \ with \\), then escape % and _ (replace each with \% and \_, respectively). This ensures that any existing backslashes do not interfere with the escaping of wildcards and that the resulting string is safe for use in SQL LIKE clauses. The change should be made in the function definition at line 376-378 in packages/rpc/src/lib/analytics-utils.ts. No new imports are needed, as this can be accomplished with regular expressions.

Suggested changeset 1
packages/rpc/src/lib/analytics-utils.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/rpc/src/lib/analytics-utils.ts b/packages/rpc/src/lib/analytics-utils.ts
--- a/packages/rpc/src/lib/analytics-utils.ts
+++ b/packages/rpc/src/lib/analytics-utils.ts
@@ -376,3 +376,4 @@
 const escapeSqlWildcards = (value: string): string => {
-	return value.replace(/[%_]/g, '\\$&');
+	// First escape backslashes, then escape % and _
+	return value.replace(/\\/g, '\\\\').replace(/[%_]/g, '\\$&');
 };
EOF
@@ -376,3 +376,4 @@
const escapeSqlWildcards = (value: string): string => {
return value.replace(/[%_]/g, '\\$&');
// First escape backslashes, then escape % and _
return value.replace(/\\/g, '\\\\').replace(/[%_]/g, '\\$&');
};
Copilot is powered by AI and may make mistakes. Always verify output.
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.

2 participants