Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@marcusljf
Copy link
Collaborator

@marcusljf marcusljf commented Sep 17, 2025

Removed the /in/ as we'll need to verfiy both company and individual pages shortly. The /in/ is just for individuals.

CleanShot 2025-09-16 at 21 20 57@2x

Summary by CodeRabbit

  • Style

    • Updated the LinkedIn field prefix in the Online Presence form from “linkedin.com/in” to “linkedin.com” for clearer guidance; purely a visual label change with no impact on validation or data binding.
  • Bug Fixes

    • Improved LinkedIn input handling to also accept company page URLs (e.g., linkedin.com/company/...), broadening accepted LinkedIn patterns.

Removed the /in/ as we'll need to verfiy company and individual pages shortly. The /in/ is just for individuals.
@vercel
Copy link
Contributor

vercel bot commented Sep 17, 2025

@marcusljf is attempting to deploy a commit to the Dub Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 17, 2025

Walkthrough

Updated the LinkedIn input label in the OnlinePresenceForm from "linkedin.com/in" to "linkedin.com", and extended LinkedIn handle parsing in social-utils to accept both personal (in/) and company (company/) URL patterns; no exported API signatures changed.

Changes

Cohort / File(s) Summary of Changes
Online Presence UI
apps/web/ui/partners/online-presence-form.tsx
Changed the LinkedIn input prefix text from "linkedin.com/in" to "linkedin.com"; no logic, handlers, validation, or data-flow changes.
Social utils (LinkedIn parsing)
apps/web/lib/social-utils.ts
Expanded LinkedIn regex to allow in/ or company/ path segments when extracting handles (pattern changed from (?:in/)? to `(?:in/

Sequence Diagram(s)

(omitted — changes are presentational and regex-only, not control-flow.)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • TWilson023

Poem

A rabbit nibble, joyous grin,
Changed a label, widened kin.
"linkedin.com" now sings so free,
Company or person — both can be.
Hop, patch, and ship — a small delight 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "LinkedIn field update" accurately and concisely reflects the primary changes in this PR—both the UI label change in the LinkedIn input (removing the "/in/" prefix) and the social-utils pattern update to support company and individual LinkedIn paths—so it is relevant, specific enough for history, and free of noise.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ 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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/web/lib/social-utils.ts (1)

92-95: Also strip URL fragments (#...).

Minor hygiene to avoid keeping anchors like “#experience”.

Apply this diff:

   handle = handle
     .replace(/\/.*$/, "")
     .replace(/\?.*$/, "")
+    .replace(/#.*$/, "")
     .replace(allowedChars, "");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a09fc7a and b90ea83.

📒 Files selected for processing (1)
  • apps/web/lib/social-utils.ts (1 hunks)
⏰ 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: Vade Review
🔇 Additional comments (1)
apps/web/lib/social-utils.ts (1)

31-35: Ensure LinkedIn link builders preserve or infer company vs individual type

Found only sanitizeSocialHandle(input, "linkedin") at apps/web/lib/actions/partners/update-online-presence.ts:39; search for 'linkedin.com/(in|company)' returned no matches. If only the slug is stored, downstream link construction must either persist the type, infer it, or attempt both '/in/' and '/company/' when generating URLs.

},
linkedin: {
patterns: [/^(?:.*\.)?linkedin\.com\/(?:in\/)?([^\/\?]+)/i],
patterns: [/^(?:.*\.)?linkedin\.com\/(?:in\/|company\/)?([^\/\?]+)/i],
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle path-only inputs and avoid false positives.

With the UI prefix now “linkedin.com”, users may enter “in/”, “company/”, or a bare slug. The current regex only matches when the host is present and can also accept unrelated sections (e.g., “groups”). Tighten and expand patterns to: (a) require in|company when a host is present; (b) support path-only inputs; (c) optionally allow bare slugs.

Apply this diff:

-    patterns: [/^(?:.*\.)?linkedin\.com\/(?:in\/|company\/)?([^\/\?]+)/i],
+    patterns: [
+      /^(?:.*\.)?linkedin\.com\/(?:in|company)\/([^\/\?#]+)/i,
+      /^(?:in|company)\/([^\/\?#]+)/i,
+      /^([^\/\?#]+)$/i,
+    ],
📝 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
patterns: [/^(?:.*\.)?linkedin\.com\/(?:in\/|company\/)?([^\/\?]+)/i],
patterns: [
/^(?:.*\.)?linkedin\.com\/(?:in|company)\/([^\/\?#]+)/i,
/^(?:in|company)\/([^\/\?#]+)/i,
/^([^\/\?#]+)$/i,
],
🤖 Prompt for AI Agents
In apps/web/lib/social-utils.ts around line 32, the LinkedIn pattern should be
tightened and expanded: replace the current host-optional regex with a set of
alternatives that (1) when a host is present requires the path to start with in/
or company/, (2) supports path-only inputs like "in/slug" or "company/slug" (no
host), and (3) also optionally accepts a bare slug; implement this by using a
single combined regex that matches either: full URLs with an optional subdomain
but mandates the path prefix (in|company), OR path-only entries that start with
(in|company)/, OR bare slugs (alphanumeric/dashes/underscores) as a fallback,
and ensure the capture group extracts only the slug portion.

Copy link
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

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

Additional Comments:

apps/web/ui/partners/online-presence-summary.tsx (lines 66-66):

LinkedIn company pages will generate broken links because the summary component hardcodes /in/ path for all LinkedIn profiles, but the form now accepts both individual profiles (/in/) and company pages (/company/).

View Details
📝 Patch Details
diff --git a/apps/web/lib/social-utils.ts b/apps/web/lib/social-utils.ts
index 7abf34bab..b2a7aa188 100644
--- a/apps/web/lib/social-utils.ts
+++ b/apps/web/lib/social-utils.ts
@@ -29,7 +29,10 @@ const PLATFORM_CONFIGS: Record<SocialPlatform, SocialPlatformConfig> = {
     maxLength: 15,
   },
   linkedin: {
-    patterns: [/^(?:.*\.)?linkedin\.com\/(?:in\/|company\/)?([^\/\?]+)/i],
+    patterns: [
+      /^(?:.*\.)?linkedin\.com\/(in\/|company\/)([^\/\?]+)/i,
+      /^(?:.*\.)?linkedin\.com\/([^\/\?]+)/i // fallback for URLs without explicit type
+    ],
     allowedChars: /[^\w-]/g,
     maxLength: 30,
   },
@@ -84,15 +87,38 @@ export const sanitizeSocialHandle = (
     const match = handle.match(pattern);
 
     if (match) {
-      handle = match[1];
+      if (platform === "linkedin" && match[1] && match[2]) {
+        // For LinkedIn, preserve the URL type (in/ or company/) as a prefix
+        const urlType = match[1]; // "in/" or "company/"
+        const actualHandle = match[2];
+        handle = `${urlType}${actualHandle}`;
+      } else {
+        // For other platforms or LinkedIn URLs without explicit type, use the handle as-is
+        handle = match[1] || match[2] || match[0];
+      }
       break;
     }
   }
 
-  handle = handle
-    .replace(/\/.*$/, "")
-    .replace(/\?.*$/, "")
-    .replace(allowedChars, "");
+  // Clean up the handle, but preserve LinkedIn prefixes
+  if (platform === "linkedin" && (handle.startsWith('in/') || handle.startsWith('company/'))) {
+    // For prefixed LinkedIn handles, only clean the handle part
+    const parts = handle.split('/');
+    if (parts.length === 2) {
+      const prefix = parts[0] + '/';
+      let cleanHandle = parts[1]
+        .replace(/\/.*$/, "")
+        .replace(/\?.*$/, "")
+        .replace(allowedChars, "");
+      handle = prefix + cleanHandle;
+    }
+  } else {
+    // Regular cleanup for other platforms
+    handle = handle
+      .replace(/\/.*$/, "")
+      .replace(/\?.*$/, "")
+      .replace(allowedChars, "");
+  }
 
   if (maxLength) {
     handle = handle.substring(0, maxLength);
diff --git a/apps/web/ui/partners/online-presence-form.tsx b/apps/web/ui/partners/online-presence-form.tsx
index e04778ae6..c1d4d30b4 100644
--- a/apps/web/ui/partners/online-presence-form.tsx
+++ b/apps/web/ui/partners/online-presence-form.tsx
@@ -70,12 +70,25 @@ interface OnlinePresenceFormProps {
 export function useOnlinePresenceForm({
   partner,
 }: Pick<OnlinePresenceFormProps, "partner">) {
+  // Extract clean LinkedIn handle for display
+  const getCleanLinkedInHandle = (linkedinValue?: string | null) => {
+    if (!linkedinValue) return undefined;
+    
+    // Remove prefixes for display in form
+    if (linkedinValue.startsWith('company/')) {
+      return linkedinValue.substring(8);
+    } else if (linkedinValue.startsWith('in/')) {
+      return linkedinValue.substring(3);
+    }
+    return linkedinValue;
+  };
+
   return useForm<OnlinePresenceFormData>({
     defaultValues: {
       website: partner?.website ? getPrettyUrl(partner.website) : undefined,
       youtube: partner?.youtube || undefined,
       twitter: partner?.twitter || undefined,
-      linkedin: partner?.linkedin || undefined,
+      linkedin: getCleanLinkedInHandle(partner?.linkedin),
       instagram: partner?.instagram || undefined,
       tiktok: partner?.tiktok || undefined,
     },
@@ -294,7 +307,7 @@ export const OnlinePresenceForm = forwardRef<
               <FormRow
                 label="LinkedIn"
                 property="linkedin"
-                prefix="in/"
+                prefix={""}
                 verifiedAtField="linkedinVerifiedAt"
                 icon={LinkedIn}
                 onVerifyClick={() =>
diff --git a/apps/web/ui/partners/online-presence-summary.tsx b/apps/web/ui/partners/online-presence-summary.tsx
index 497c64807..0f1ecb9b3 100644
--- a/apps/web/ui/partners/online-presence-summary.tsx
+++ b/apps/web/ui/partners/online-presence-summary.tsx
@@ -60,11 +60,40 @@ const fields: {
   {
     label: "LinkedIn",
     icon: LinkedIn,
-    data: (partner) => ({
-      value: partner.linkedin,
-      verified: !!partner.linkedinVerifiedAt,
-      href: `https://linkedin.com/in/${partner.linkedin}`,
-    }),
+    data: (partner) => {
+      if (!partner.linkedin) {
+        return {
+          value: null,
+          verified: false,
+          href: null,
+        };
+      }
+
+      // Handle prefixed LinkedIn handles that preserve URL type
+      const isCompanyPage = partner.linkedin.startsWith('company/');
+      const isIndividualProfile = partner.linkedin.startsWith('in/');
+      
+      let href: string;
+      let displayValue: string;
+      
+      if (isCompanyPage) {
+        href = `https://linkedin.com/${partner.linkedin}`;
+        displayValue = partner.linkedin.substring(8); // Remove 'company/' prefix
+      } else if (isIndividualProfile) {
+        href = `https://linkedin.com/${partner.linkedin}`;
+        displayValue = partner.linkedin.substring(3); // Remove 'in/' prefix
+      } else {
+        // Legacy data without prefix - assume individual profile
+        href = `https://linkedin.com/in/${partner.linkedin}`;
+        displayValue = partner.linkedin;
+      }
+      
+      return {
+        value: displayValue,
+        verified: !!partner.linkedinVerifiedAt,
+        href,
+      };
+    },
   },
   {
     label: "Instagram",

Analysis

LinkedIn company pages generate broken links due to hardcoded /in/ path in summary component

What fails: OnlinePresenceSummary component in apps/web/ui/partners/online-presence-summary.tsx hardcodes /in/ path for all LinkedIn profiles (line 66), but form accepts both individual profiles (/in/) and company pages (/company/)

How to reproduce:

# 1. Enter company LinkedIn URL in form: https://linkedin.com/company/acme-corp
# 2. Form sanitizes to handle: "acme-corp" (losing URL type information)  
# 3. Summary reconstructs as: https://linkedin.com/in/acme-corp (incorrect)
# 4. Click link - leads to 404 because company pages use /company/ not /in/

Result: All LinkedIn company page links are broken, generating 404s when clicked

Expected: Company URLs should reconstruct as https://linkedin.com/company/acme-corp per LinkedIn's official company page URL format

Root cause: sanitizeSocialHandle() in social-utils.ts strips URL type information, and summary component assumes all LinkedIn URLs are individual profiles

@steven-tey steven-tey closed this Oct 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