Skip to content

feat(opensource): add guide sharing button and dynamic open graph pre…#1460

Open
Rajal-ui wants to merge 1 commit into
Sachinchaurasiya360:mainfrom
Rajal-ui:feat/share-guides-with-og-previews
Open

feat(opensource): add guide sharing button and dynamic open graph pre…#1460
Rajal-ui wants to merge 1 commit into
Sachinchaurasiya360:mainfrom
Rajal-ui:feat/share-guides-with-og-previews

Conversation

@Rajal-ui
Copy link
Copy Markdown
Contributor

@Rajal-ui Rajal-ui commented Jun 5, 2026

Description

This PR addresses the missing sharing mechanics across our student open-source curriculum guides. It introduces an interactive share utility with instant clipboard copies directly on the main landing grid cards and configures guide route headers to serve context-aware, static Open Graph (og:image) assets for high-quality link previews on channels like WhatsApp, Twitter, or Discord.

Key Changes

  • Card Upgrades (GuidanceCards.tsx): Mounted a clean, accessible <Button> container featuring the Share2 icon layout within each individual grid cell. Isolated click events using e.preventDefault() and e.stopPropagation() to safely intercept actions without accidentally triggering parent <Link> navigation paths.
  • Layout Enhancements (GuideListPage.tsx): Extended the base wrapper component to accept and process dynamic ogImage file references mapping to our public directory layer (client/public/og/).
  • Route Coverage: Injected precise meta properties across all guide screens (FirstPRRoadmapPage.tsx, GSoCProposalPage.tsx, ProgramTrackerPage.tsx, GSoCReposPage.tsx, and all markdown/cheatsheet sub-document panels).
  • Code Quality Cleanup: Resolved a pre-existing TypeScript compilation mismatch inside FirstPRRoadmapPage.tsx regarding missing properties on the secondary ConfirmDialog system and cleared uninitialized references inside ProgramTrackerPage.tsx.

Related Issue

Fixes #1020

Type of Change

  • Bug Fix
  • Feature
  • Enhancement
  • Documentation

Testing

  1. Clipboard Performance: Navigated to the open-source guides section and interacted with the card share actions. Verified that absolute canonical path strings (e.g., https://www.internhack.xyz/student/opensource/first-pr) load cleanly into system clipboard memory.
  2. Meta Elements Verification: Inspected the pre-rendered HTML DOM tree headers across isolated guide routes to confirm that <meta property="og:image" content="..." /> tags point exactly to their intended public folder asset targets.
  3. Build Check Pass: Ran local type verification validation (npx tsc --noEmit) to ensure zero errors were introduced across the edited files.

Screenshots / Video

image
image

Checklist

  • Code follows project guidelines
  • No new compile/type errors
  • Tested manually (include steps above)
  • No .env, credentials, or node_modules committed
  • Docs updated (if needed)
  • Screenshot or video attached for every UI change (PR will be rejected if missing)

Summary by CodeRabbit

  • New Features

    • Added share button to guidance cards for quick social sharing.
  • Improvements

    • Improved Open Graph images across student resources pages for better link previews on social media.
    • Enhanced SEO metadata on program tracker and other resource pages for improved search visibility.

@github-actions github-actions Bot added the enhancement New feature or request label Jun 5, 2026
@github-actions github-actions Bot added gssoc quality:exceptional Exceptional implementation quality level:intermediate Requires moderate project understanding scope:frontend Changes to client-side / UI code gssoc:approved Approved for GSSoC scoring type:design UI/UX or design-related updates type:docs Documentation-related changes type:feature New feature implementation labels Jun 5, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

Hi @Rajal-ui, thanks for contributing to InternHack! 🎉

I have automatically:

  • 👤 Assigned this PR to you.
  • 🏷️ Applied the gssoc:approved label.

Our workflows will now analyze your changes to classify:

  • 📈 PR Difficulty: level:*
  • 🧩 PR Type: type:*
  • 🌟 PR Quality: quality:*

Tip

Ensure your PR description references the issue it resolves (e.g. Closes #123). This allows the bot to inherit any additional labels from that issue!

Happy coding! 🚀

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements Open Graph image metadata for guide pages and adds a share-to-clipboard feature. GuideListPage gains an optional ogImage prop; multiple guide pages now pass image paths to enable link previews on social platforms. GuidanceCards adds a share button that copies card URLs to the clipboard with toast feedback. ProgramTrackerPage receives full SEO support, and FirstPRRoadmapPage's ConfirmDialog props are refined.

Changes

Open Graph Image Propagation & Share Feature

Layer / File(s) Summary
GuideListPage ogImage contract
client/src/module/student/opensource/components/GuideListPage.tsx
GuideListPage now accepts optional ogImage?: string prop and forwards it to the SEO component for Open Graph metadata.
Guide pages — ogImage propagation
client/src/module/student/opensource/CICDGuidePage.tsx, CommTemplatesPage.tsx, FirstPRRoadmapPage.tsx, GSoCProposalPage.tsx, GSoCReposPage.tsx, GitCheatsheetPage.tsx, ReadCodebasePage.tsx
Seven guide pages now pass ogImage paths (e.g., /og/og-cicd.png, /og/og-communication.png) to GuideListPage or SEO component for social link previews.
ProgramTrackerPage SEO metadata
client/src/module/student/opensource/ProgramTrackerPage.tsx
ProgramTrackerPage imports SEO and canonicalUrl, then renders an SEO component with title, description, keywords, canonical URL, and ogImage for the programs page.
GuidanceCards share button
client/src/module/student/opensource/GuidanceCards.tsx
GuidanceCards imports useCallback, Button, toast, Share2 icon, and SITE_URL; adds handleShare callback to build and copy card URLs to clipboard; updates card layout with hover-revealed share button and adjusted icon/title styling.
FirstPRRoadmapPage ConfirmDialog update
client/src/module/student/opensource/FirstPRRoadmapPage.tsx
Reset confirmation dialog updated to use onCancel callback and confirmVariant prop instead of variant.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested labels

level:intermediate, type:feature, enhancement, scope:frontend, quality:clean

Suggested reviewers

  • Sachinchaurasiya360

Poem

🐰 A guide to share with every friend,
With images that blend and blend,
Click the button, copy the link,
Toast it quick—what do you think?
Open Graph now sparkles bright,
Social shares feel just right!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title is truncated and incomplete (ends with 'pre…'), making it unclear what the full feature is about despite addressing guide sharing and Open Graph previews. Complete the PR title to clearly state the feature: e.g., 'feat(opensource): add guide sharing button and dynamic open graph previews'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is comprehensive, covering key changes, testing approach, and includes screenshots. However, the checklist item 'Screenshot or video attached for every UI change' is marked as unchecked despite UI changes being present.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issue #1020: adds a share button with clipboard functionality and toast feedback, and provides Open Graph images across all guide routes with proper meta tags.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #1020 objectives. Additionally, the PR includes bug fixes (ConfirmDialog TypeScript issues in FirstPRRoadmapPage.tsx and uninitialized references in ProgramTrackerPage.tsx) that are pre-existing quality issues rather than scope creep.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown
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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/module/student/opensource/FirstPRRoadmapPage.tsx`:
- Line 158: The loading-state SEO component in FirstPRRoadmapPage is missing the
ogImage prop; update the SEO invocation used for the loading skeleton (the same
props used in the main render) to include ogImage="/og/og-first-pr.png" so both
SEO components have identical Open Graph metadata.

In `@client/src/module/student/opensource/GuidanceCards.tsx`:
- Line 70: In the GuidanceCards.tsx span where the className contains the
arbitrary token "text-[10px]" (the span with className="... text-[10px]
font-mono uppercase tracking-widest ..."), replace that arbitrary size with a
canonical Tailwind size such as "text-xs" and, if needed, tweak adjacent
utilities like tracking-widest or opacity/color classes (e.g., adjust tracking
or group-hover:text-lime-500) to match the original visual appearance; update
only the className on that span inside the GuidanceCards component to remove
bracketed sizing and use the standard scale token.
- Around line 65-83: The share Button is nested inside a Link
(interactive-in-interactive); move the Button out of the Link container in
GuidanceCards.tsx so it is a sibling (or positioned absolutely) instead of a
child, keep the onClick handler (handleShare) and title/aria-label on the
Button, and update styles/layout so the visual appearance is unchanged; ensure
the Button's onClick calls e.stopPropagation() / e.preventDefault() as needed so
clicking Share does not trigger Link navigation and that the Button remains
keyboard-focusable and accessible.
- Around line 33-42: The handleShare handler calls
navigator.clipboard.writeText(url) without guarding for navigator.clipboard
support; update the handleShare function to first check that navigator and
navigator.clipboard and navigator.clipboard.writeText exist, and if not
immediately show toast.error("Clipboard not supported" or similar) and return;
if supported, call writeText inside a Promise/try-catch (preserve the existing
.then/.catch or await with try/catch) so synchronous exceptions are caught and
the success/failure toasts still fire. Reference: handleShare (useCallback) and
the use of navigator.clipboard.writeText(url) to find where to add the guard and
error fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8df66001-d7ef-4198-80c7-b8f6a44440f9

📥 Commits

Reviewing files that changed from the base of the PR and between 0c176ae and 7d7013a.

📒 Files selected for processing (10)
  • client/src/module/student/opensource/CICDGuidePage.tsx
  • client/src/module/student/opensource/CommTemplatesPage.tsx
  • client/src/module/student/opensource/FirstPRRoadmapPage.tsx
  • client/src/module/student/opensource/GSoCProposalPage.tsx
  • client/src/module/student/opensource/GSoCReposPage.tsx
  • client/src/module/student/opensource/GitCheatsheetPage.tsx
  • client/src/module/student/opensource/GuidanceCards.tsx
  • client/src/module/student/opensource/ProgramTrackerPage.tsx
  • client/src/module/student/opensource/ReadCodebasePage.tsx
  • client/src/module/student/opensource/components/GuideListPage.tsx

description="Step-by-step roadmap to making your first pull request on GitHub. Learn git workflow, finding issues, and contributing to open source projects."
keywords="first pull request, open source contribution, GitHub beginner, git workflow, contribute to open source"
canonicalUrl={canonicalUrl("/student/opensource/first-pr")}
ogImage="/og/og-first-pr.png"
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 | 🟡 Minor | ⚡ Quick win

Add ogImage to the loading state SEO component for consistency.

The loading skeleton's SEO component (lines 100-105) is missing the ogImage prop that was added here on line 158. Both SEO components should have identical metadata to ensure consistent Open Graph previews regardless of loading state.

🔧 Proposed fix

Add the same ogImage prop to the SEO component in the loading state:

       <SEO
         title="First Pull Request Guide - Open Source for Beginners"
         description="Step-by-step roadmap to making your first pull request on GitHub. Learn git workflow, finding issues, and contributing to open source projects."
         keywords="first pull request, open source contribution, GitHub beginner, git workflow, contribute to open source"
         canonicalUrl={canonicalUrl("/student/opensource/first-pr")}
+        ogImage="/og/og-first-pr.png"
       />
📝 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
ogImage="/og/og-first-pr.png"
<SEO
title="First Pull Request Guide - Open Source for Beginners"
description="Step-by-step roadmap to making your first pull request on GitHub. Learn git workflow, finding issues, and contributing to open source projects."
keywords="first pull request, open source contribution, GitHub beginner, git workflow, contribute to open source"
canonicalUrl={canonicalUrl("/student/opensource/first-pr")}
ogImage="/og/og-first-pr.png"
/>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/module/student/opensource/FirstPRRoadmapPage.tsx` at line 158, The
loading-state SEO component in FirstPRRoadmapPage is missing the ogImage prop;
update the SEO invocation used for the loading skeleton (the same props used in
the main render) to include ogImage="/og/og-first-pr.png" so both SEO components
have identical Open Graph metadata.

Comment on lines +33 to +42
const handleShare = useCallback((e: React.MouseEvent, path: string) => {
e.preventDefault();
e.stopPropagation();

const url = `${SITE_URL}${path}`;
void navigator.clipboard.writeText(url).then(() => {
toast.success("Link copied to clipboard!");
}).catch(() => {
toast.error("Failed to copy link.");
});
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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and show the relevant portion of the file
FILE="client/src/module/student/opensource/GuidanceCards.tsx"
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE"
  exit 1
fi

echo "---- file: $FILE (lines 1-120) ----"
nl -ba "$FILE" | sed -n '1,120p'

echo "---- file: $FILE (lines 20-80) ----"
nl -ba "$FILE" | sed -n '20,80p'

Repository: Sachinchaurasiya360/InternHack

Length of output: 221


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="client/src/module/student/opensource/GuidanceCards.tsx"
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE"
  exit 1
fi

echo "---- file: $FILE (lines 1-140) ----"
cat -n "$FILE" | sed -n '1,140p'

echo "---- file: $FILE (lines 30-80) ----"
cat -n "$FILE" | sed -n '30,80p'

Repository: Sachinchaurasiya360/InternHack

Length of output: 8486


Guard navigator.clipboard.writeText support before calling it
At line 38, navigator.clipboard.writeText(url) is called without checking availability; if navigator.clipboard is undefined, it can throw synchronously and the .catch(...) toast won’t run. Add a capability guard with a fallback toast.

Minimal guard
- const url = `${SITE_URL}${path}`;
- void navigator.clipboard.writeText(url).then(() => {
+ const url = `${SITE_URL}${path}`;
+ if (!navigator.clipboard?.writeText) {
+   toast.error("Clipboard is not supported in this browser.");
+   return;
+ }
+ void navigator.clipboard.writeText(url).then(() => {
    toast.success("Link copied to clipboard!");
  }).catch(() => {
    toast.error("Failed to copy link.");
  });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/module/student/opensource/GuidanceCards.tsx` around lines 33 - 42,
The handleShare handler calls navigator.clipboard.writeText(url) without
guarding for navigator.clipboard support; update the handleShare function to
first check that navigator and navigator.clipboard and
navigator.clipboard.writeText exist, and if not immediately show
toast.error("Clipboard not supported" or similar) and return; if supported, call
writeText inside a Promise/try-catch (preserve the existing .then/.catch or
await with try/catch) so synchronous exceptions are caught and the
success/failure toasts still fire. Reference: handleShare (useCallback) and the
use of navigator.clipboard.writeText(url) to find where to add the guard and
error fallback.

Comment on lines 65 to +83
<Link
to={card.to}
className="group relative flex flex-col gap-3 p-4 h-full bg-white dark:bg-stone-900 border-r border-b border-stone-200 dark:border-white/10 no-underline hover:bg-stone-900 dark:hover:bg-stone-50 transition-colors"
className="flex flex-col gap-3 p-4 h-full bg-white dark:bg-stone-900 border-r border-b border-stone-200 dark:border-white/10 no-underline hover:bg-stone-50 dark:hover:bg-stone-800 transition-colors"
>
<div className="flex items-center justify-between">
<span className="text-[10px] font-mono uppercase tracking-widest text-stone-500 dark:text-stone-400 group-hover:text-lime-400">
<span className="text-[10px] font-mono uppercase tracking-widest text-stone-500 dark:text-stone-400 group-hover:text-lime-500 transition-colors">
/ {String(i + 1).padStart(2, "0")}
</span>
<div className="w-8 h-8 rounded-md bg-stone-100 dark:bg-white/5 group-hover:bg-white/10 dark:group-hover:bg-stone-900/10 flex items-center justify-center transition-colors">
<card.icon className="w-4 h-4 text-stone-700 dark:text-stone-300 group-hover:text-lime-400" aria-hidden />
<div className="flex items-center gap-2">
<Button
variant="ghost"
mode="icon"
size="sm"
className="h-8 w-8 rounded-md opacity-0 group-hover:opacity-100 transition-all hover:bg-lime-400/10 hover:text-lime-600 dark:hover:text-lime-400"
onClick={(e) => handleShare(e, card.to)}
title="Share Guide"
>
<Share2 className="w-3.5 h-3.5" />
</Button>
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 | 🟠 Major | 🏗️ Heavy lift

Avoid nesting Button inside Link (interactive-in-interactive).

At Line 65-83, the share Button is rendered inside a Link. This is invalid interactive nesting and can produce inconsistent click/focus behavior for keyboard and assistive-tech users.

Suggested structure change
- <Link to={card.to} className="...">
-   ...
-   <Button onClick={(e) => handleShare(e, card.to)} ... />
-   ...
- </Link>
+ <div className="relative">
+   <Link to={card.to} className="...">
+     ...
+   </Link>
+   <Button
+     variant="ghost"
+     mode="icon"
+     size="sm"
+     className="absolute top-3 right-3 h-8 w-8 rounded-md ..."
+     onClick={(e) => handleShare(e, card.to)}
+     title="Share Guide"
+   >
+     <Share2 className="w-3.5 h-3.5" />
+   </Button>
+ </div>

As per coding guidelines, interactive UI should use accessible patterns and this change currently introduces a non-compliant nested interaction model.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/module/student/opensource/GuidanceCards.tsx` around lines 65 - 83,
The share Button is nested inside a Link (interactive-in-interactive); move the
Button out of the Link container in GuidanceCards.tsx so it is a sibling (or
positioned absolutely) instead of a child, keep the onClick handler
(handleShare) and title/aria-label on the Button, and update styles/layout so
the visual appearance is unchanged; ensure the Button's onClick calls
e.stopPropagation() / e.preventDefault() as needed so clicking Share does not
trigger Link navigation and that the Button remains keyboard-focusable and
accessible.

>
<div className="flex items-center justify-between">
<span className="text-[10px] font-mono uppercase tracking-widest text-stone-500 dark:text-stone-400 group-hover:text-lime-400">
<span className="text-[10px] font-mono uppercase tracking-widest text-stone-500 dark:text-stone-400 group-hover:text-lime-500 transition-colors">
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 | 🟡 Minor | ⚡ Quick win

Replace arbitrary Tailwind text size with canonical scale class.

At Line 70, text-[10px] violates the Tailwind class rule. Please switch to a standard size token (for example text-xs) and adjust tracking/opacity if needed for visual parity.

As per coding guidelines, do not use arbitrary bracket sizes like text-[17px]; use standard scale classes instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/module/student/opensource/GuidanceCards.tsx` at line 70, In the
GuidanceCards.tsx span where the className contains the arbitrary token
"text-[10px]" (the span with className="... text-[10px] font-mono uppercase
tracking-widest ..."), replace that arbitrary size with a canonical Tailwind
size such as "text-xs" and, if needed, tweak adjacent utilities like
tracking-widest or opacity/color classes (e.g., adjust tracking or
group-hover:text-lime-500) to match the original visual appearance; update only
the className on that span inside the GuidanceCards component to remove
bracketed sizing and use the standard scale token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request gssoc:approved Approved for GSSoC scoring gssoc level:intermediate Requires moderate project understanding quality:exceptional Exceptional implementation quality scope:frontend Changes to client-side / UI code type:design UI/UX or design-related updates type:docs Documentation-related changes type:feature New feature implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add 'share this guide' button — shareable URL with og:image for each guide

1 participant