Skip to content

Comments

Make referrers clickable. #69

Merged
izadoesdev merged 1 commit intodatabuddy-analytics:stagingfrom
sbansal1999:make-referrers-clickable
Aug 11, 2025
Merged

Make referrers clickable. #69
izadoesdev merged 1 commit intodatabuddy-analytics:stagingfrom
sbansal1999:make-referrers-clickable

Conversation

@sbansal1999
Copy link
Contributor

@sbansal1999 sbansal1999 commented Aug 9, 2025

Fixes part of #26.

Bonus if a tooltip is added to provide more info (Like name, domain, etc)

Not sure, what can be shown there as we already are showing the domain/name.

Summary by CodeRabbit

  • New Features
    • Referrer sources with valid domains now display as clickable links that open in a new tab.
  • Style
    • Updated styling for referrer sources, including improved hover effects and consistent layout.

@vercel
Copy link

vercel bot commented Aug 9, 2025

@sbansal1999 is attempting to deploy a commit to the Databuddy Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 9, 2025

Walkthrough

The ReferrerSourceCell component was updated to render a clickable anchor element linking to the referrer's domain when appropriate, instead of a static span. The anchor includes security and accessibility attributes, uses a utility for class name composition, and retains the favicon and display name. Imports were updated accordingly.

Changes

Cohort / File(s) Change Summary
ReferrerSourceCell rendering & styling
apps/dashboard/components/atomic/ReferrerSourceCell.tsx
Updated to render an anchor (<a>) linking to the domain for non-"Direct" referrers, added security attributes, used a class name utility, and adjusted imports.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 93862b6 and 0ad3773.

📒 Files selected for processing (1)
  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

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

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

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use TypeScript namespaces.
Don't use the TypeScript directive @ts-ignore.
Don't use any type.
Don't use implicit any type on variable declarations.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't declare empty interfaces.
Use export type for types.
Use import type for types.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{js,jsx,ts,tsx,css,scss}

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

Always use rounded, not rounded-xl or rounded-md, always rounded

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{jsx,tsx}

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

**/*.{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
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 elements in Next.js projects.
Don't use elements in Next.js projects.
Don't pass children as props.
Don't use the return value of React.render.
Make sure all dependencies are correctly specified in React hooks.
Make sure all React hooks are called from the top level of component functions.
Don't forget key props in iterators and collection literals.
Don't destructure props inside JSX components in Solid projects.
Don't define React components inside other components.
Don't use event handlers on non-interactive elements.
Don't assign to React component props.
Don't use both children and dangerouslySetInnerHTML props on the same element.
Don't use dangerous JSX props.
Don't use Array index in keys.
Don't insert comments as text nodes.
Don't assign JSX properties multiple times.
Don't add extra closing tags for components without children.
Use <>...</> instead of ....
Watch out for possible "wrong" semicolons inside JSX elements.
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 or .
Only use the scope prop on 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 exp...

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{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}: Use bun <file> instead of node <file> or ts-node <file>
Do not use dotenv; Bun automatically loads .env files
Do not use express; use Bun.serve() for HTTP servers
Do not use better-sqlite3; use bun:sqlite for SQLite
Do not use ioredis; use Bun.redis for Redis
Do not use pg or postgres.js; use Bun.sql for Postgres
Do not use ws; use built-in WebSocket
Prefer Bun.file over node:fs's readFile/writeFile
Use Bun.$ instead of execa for running shell commands

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{js,ts,jsx,tsx}

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

**/*.{js,ts,jsx,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't use global eval().
Don't use var.
Don't use console.
Don't use debugger.
Don't assign directly to document.cookie.
Don't use duplicate case labels.
Don't use duplicate class members.
Don't use duplicate function parameter names.
Don't use empty block statements and static blocks.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Use for...of statements instead of Array.forEach.
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 possible.
Don't use number literal object member names that aren't base 10 or use underscore separators.
Remove redundant terms from logical expressions.
Use while loops instead of for loops when you don't need initializer and update expressions.
Don't reassign const variables.
Don't use constant expressions in conditions.
Don't use Math.min and Math.max to clamp values when the result is constant.
Don't return a value from a constructor.
Don't use empty character classes in regular expression literals.
Don't use empty destructuring patterns.
Don't call global object properties as functions.
Don't declare functions and vars that are accessible outside their block.
Don't use variables and function parameters before they're declared.
Don't use 8 and 9 escape sequences in string literals.
Don't use literal numbers that lose precision.
Don't use duplicate conditions in if-else-if chains.
Don't use two keys with the same name inside objects...

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
🧠 Learnings (21)
📓 Common learnings
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all anchors are valid and navigable.
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure anchors have content that's accessible to screen readers.
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make static elements with click handlers use a valid role attribute.
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all anchors are valid and navigable.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure anchors have content that's accessible to screen readers.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make static elements with click handlers use a valid role attribute.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Use semantic elements instead of role attributes in JSX.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't assign interactive ARIA roles to non-interactive HTML elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't use explicit role property that's the same as the implicit/default role.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't assign non-interactive ARIA roles to interactive HTML elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Always include a title attribute for iframe elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.054Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.054Z
Learning: Applies to **/*.{jsx,tsx} : Use <>...</> instead of <Fragment>...</Fragment>.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Ensure all ARIA properties (aria-*) are valid.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Use valid ARIA state and property values.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure ARIA properties are valid for the element's supported roles.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Use valid values for the autocomplete attribute on input elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.054Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.054Z
Learning: Applies to **/*.{jsx,tsx} : Don't use dangerous JSX props.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.054Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.054Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Don't use unsafe negation.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't set aria-hidden="true" on focusable elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:40:18.511Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-29T15:40:18.511Z
Learning: Applies to **/*.{jsx,tsx} : use Icon at the end of phosphor react icons, like CaretIcon not Caret

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Accompany onMouseOver/onMouseOut with onFocus/onBlur.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Give all elements requiring alt text meaningful information for screen readers.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
🔇 Additional comments (2)
apps/dashboard/components/atomic/ReferrerSourceCell.tsx (2)

4-4: LGTM: class composition via cn

Using cn for class merging is consistent with our patterns.


48-49: Good security defaults for external links

target="_blank" with rel="noopener noreferrer nofollow" is correct for external/untrusted referrers.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
  • 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.

Support

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

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.

@sbansal1999 sbansal1999 changed the base branch from main to staging August 9, 2025 13:19
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (3)
apps/dashboard/components/atomic/ReferrerSourceCell.tsx (3)

27-28: Guard against whitespace-only domains

If domain is a string with only spaces, the current check will still render an anchor with an invalid href. Trim before deciding.

Apply this diff:

-  if (displayName === 'Direct' || !domain) {
+  if (displayName === 'Direct' || !domain?.trim()) {

51-55: Conform to rounded class guideline

Per our CSS guideline, prefer rounded over rounded-sm.

Apply this diff:

-      className="rounded-sm"
+      className="rounded"

29-33: Use cn in the “Direct” fallback for consistency

Avoid manual string concatenation; use cn like in the link path.

Apply this diff:

-      <span
-        className={
-          className ? `${className} font-medium text-sm` : 'font-medium text-sm'
-        }
-        id={id}
-      >
+      <span className={cn('font-medium text-sm', className)} id={id}>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b270855 and 93862b6.

📒 Files selected for processing (1)
  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

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

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

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use TypeScript namespaces.
Don't use the TypeScript directive @ts-ignore.
Don't use any type.
Don't use implicit any type on variable declarations.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't declare empty interfaces.
Use export type for types.
Use import type for types.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{js,jsx,ts,tsx,css,scss}

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

Always use rounded, not rounded-xl or rounded-md, always rounded

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{jsx,tsx}

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

**/*.{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
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 elements in Next.js projects.
Don't use elements in Next.js projects.
Don't pass children as props.
Don't use the return value of React.render.
Make sure all dependencies are correctly specified in React hooks.
Make sure all React hooks are called from the top level of component functions.
Don't forget key props in iterators and collection literals.
Don't destructure props inside JSX components in Solid projects.
Don't define React components inside other components.
Don't use event handlers on non-interactive elements.
Don't assign to React component props.
Don't use both children and dangerouslySetInnerHTML props on the same element.
Don't use dangerous JSX props.
Don't use Array index in keys.
Don't insert comments as text nodes.
Don't assign JSX properties multiple times.
Don't add extra closing tags for components without children.
Use <>...</> instead of ....
Watch out for possible "wrong" semicolons inside JSX elements.
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 or .
Only use the scope prop on 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 exp...

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{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}: Use bun <file> instead of node <file> or ts-node <file>
Do not use dotenv; Bun automatically loads .env files
Do not use express; use Bun.serve() for HTTP servers
Do not use better-sqlite3; use bun:sqlite for SQLite
Do not use ioredis; use Bun.redis for Redis
Do not use pg or postgres.js; use Bun.sql for Postgres
Do not use ws; use built-in WebSocket
Prefer Bun.file over node:fs's readFile/writeFile
Use Bun.$ instead of execa for running shell commands

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
**/*.{js,ts,jsx,tsx}

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

**/*.{js,ts,jsx,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't use global eval().
Don't use var.
Don't use console.
Don't use debugger.
Don't assign directly to document.cookie.
Don't use duplicate case labels.
Don't use duplicate class members.
Don't use duplicate function parameter names.
Don't use empty block statements and static blocks.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Use for...of statements instead of Array.forEach.
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 possible.
Don't use number literal object member names that aren't base 10 or use underscore separators.
Remove redundant terms from logical expressions.
Use while loops instead of for loops when you don't need initializer and update expressions.
Don't reassign const variables.
Don't use constant expressions in conditions.
Don't use Math.min and Math.max to clamp values when the result is constant.
Don't return a value from a constructor.
Don't use empty character classes in regular expression literals.
Don't use empty destructuring patterns.
Don't call global object properties as functions.
Don't declare functions and vars that are accessible outside their block.
Don't use variables and function parameters before they're declared.
Don't use 8 and 9 escape sequences in string literals.
Don't use literal numbers that lose precision.
Don't use duplicate conditions in if-else-if chains.
Don't use two keys with the same name inside objects...

Files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all anchors are valid and navigable.
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure anchors have content that's accessible to screen readers.
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make static elements with click handlers use a valid role attribute.
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure all anchors are valid and navigable.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make sure anchors have content that's accessible to screen readers.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Make static elements with click handlers use a valid role attribute.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Use semantic elements instead of role attributes in JSX.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't assign interactive ARIA roles to non-interactive HTML elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't use explicit role property that's the same as the implicit/default role.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Always include a title attribute for iframe elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Don't assign non-interactive ARIA roles to interactive HTML elements.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Use valid, non-abstract ARIA roles for elements with ARIA roles.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:40:18.511Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/01-MUST-DO.mdc:0-0
Timestamp: 2025-07-29T15:40:18.511Z
Learning: Applies to **/*.{jsx,tsx} : use Icon at the end of phosphor react icons, like CaretIcon not Caret

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Accompany onMouseOver/onMouseOut with onFocus/onBlur.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.055Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.055Z
Learning: Applies to **/*.{jsx,tsx} : Give all elements requiring alt text meaningful information for screen readers.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
📚 Learning: 2025-07-29T15:42:01.054Z
Learnt from: CR
PR: databuddy-analytics/Databuddy#0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-29T15:42:01.054Z
Learning: Applies to **/*.{jsx,tsx} : Use <>...</> instead of <Fragment>...</Fragment>.

Applied to files:

  • apps/dashboard/components/atomic/ReferrerSourceCell.tsx
⏰ 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 (2)
apps/dashboard/components/atomic/ReferrerSourceCell.tsx (2)

4-4: Import of cn utility looks good

Consistent with local utils and used correctly below.


42-45: Class composition is solid; keep using cn for consistency

Using cn here is correct. Consider matching this approach in the “Direct” span for consistency (see separate comment).

Comment on lines 41 to 47
<a
className={cn(
'flex cursor-pointer items-center gap-2 font-medium text-sm transition-colors hover:text-blue-600 hover:underline',
className
? `${className} flex items-center gap-2 font-medium text-sm`
: 'flex items-center gap-2 font-medium text-sm'
}
)}
href={`https://${domain}`}
id={id}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Normalize and validate href to ensure links are always valid

To align with our “anchors must be valid and navigable” learning, trim and encode the URL you generate. This avoids broken links from stray whitespace and unsafe characters.

Apply this diff:

-    href={`https://${domain}`}
+    href={encodeURI(`https://${domain.trim()}`)}

Optionally, for stronger validation, introduce a small helper and use it here:

// outside the component
function getValidatedHref(raw?: string): string | null {
  if (!raw) return null;
  const trimmed = raw.trim();
  const prefixed = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
  try {
    const url = new URL(prefixed);
    return url.protocol === 'http:' || url.protocol === 'https:' ? url.toString() : null;
  } catch {
    return null;
  }
}

Then inside the component:

const href = getValidatedHref(domain);

and render span if !href.

🤖 Prompt for AI Agents
In apps/dashboard/components/atomic/ReferrerSourceCell.tsx around lines 41 to
47, the href attribute is directly constructed from the domain string without
normalization or validation, which can lead to broken or unsafe links. To fix
this, create a helper function that trims the domain, ensures it has an
http/https prefix, and validates it using the URL constructor, returning null if
invalid. Then, inside the component, use this helper to get a validated href; if
the href is null, render a span instead of an anchor to avoid invalid links.

@izadoesdev
Copy link
Member

Acknowledge coderabbit's comments please

@sbansal1999 sbansal1999 force-pushed the make-referrers-clickable branch from 93862b6 to 0ad3773 Compare August 9, 2025 14:56
@sbansal1999
Copy link
Contributor Author

sbansal1999 commented Aug 9, 2025

Changes made:

  • Added nofollow to the rel attribute.
  • Trimmed the domain link.

Question:

I wonder if we need to actually validate the URL using the function mentioned in this comment, due to how this data is coming.

@izadoesdev izadoesdev merged commit 628199f into databuddy-analytics:staging Aug 11, 2025
1 of 2 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Sep 2, 2025
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