docs: add SocialShareButton tutorial video to README#354
docs: add SocialShareButton tutorial video to README#354sneha-techiee wants to merge 1 commit intoAOSSIE-Org:mainfrom
Conversation
📝 WalkthroughWalkthroughThe changes integrate a third-party social share button widget into the website. A stylesheet and JavaScript file are loaded in the root layout, the Footer component is converted to a client component with polling logic to initialize the widget when available, and CSS styling is added for the share button. Changes
Sequence DiagramsequenceDiagram
participant Client as Browser/Client
participant RootLayout as RootLayout
participant Footer as Footer Component
participant ThirdParty as Social Share Library
Client->>RootLayout: Initial page load
RootLayout->>ThirdParty: Load stylesheet (synchronous)
RootLayout->>ThirdParty: Load JavaScript (afterInteractive)
ThirdParty-->>Client: Scripts/styles loaded
RootLayout->>Footer: Render Footer component
Footer->>Footer: useEffect hook runs
Footer->>Footer: Start 300ms polling interval
loop Poll until available
Footer->>Client: Check window.SocialShareButton
alt SocialShareButton exists
Footer->>ThirdParty: new window.SocialShareButton()
ThirdParty->>Client: Initialize widget on `#share-button`
Footer->>Footer: Clear polling interval
end
end
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 4❌ Failed checks (4 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
app/components/Layout/Footer/Footer.css (1)
73-86: Prefer scoped selectors over repeated!importantoverrides.Using
!importanton most properties will make future styling and theming harder. Scope the rule to the mount container (for example#share-button .social-share-btn) and drop the debug-style comment.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/components/Layout/Footer/Footer.css` around lines 73 - 86, The rule currently forces styles with multiple !important flags and a debug comment; instead scope the selector to the mounting container (e.g., use a parent id like `#share-button` .social-share-btn) and remove the debug comment and all !important declarations so normal cascade and theming work; update both the base selector (.social-share-btn) and the hover selector (.social-share-btn:hover) to the scoped form and keep the same properties (background, border, color, padding, border-radius, cursor, box-shadow) but without !important.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/components/Layout/Footer/index.jsx`:
- Around line 15-16: The share payload in Layout/Footer/index.jsx currently
hardcodes url: "https://aossie.org" and title: "Check out AOSSIE!" so shares
point to the wrong site; locate the share payload object in the Footer component
and replace those hardcoded values with runtime page metadata (use
window.location.href and document.title), guarding for SSR by checking typeof
window !== 'undefined' and falling back to sensible defaults (e.g., site home
URL and a default title) so the share uses the current page URL and title when
available.
- Around line 10-22: The useEffect polling loop that creates new
window.SocialShareButton (uses interval variable inside useEffect) can run
indefinitely if the external script never loads; modify the effect to add a
retry cap and a timeout: track attempts (e.g., maxAttempts) or an elapsed start
time inside the effect, increment attempts each tick and clearInterval(interval)
and stop trying once the cap/time is reached, and optionally log or show a
failure; keep the existing creation code that instantiates new
window.SocialShareButton({ container: "#share-button", url: "...", title: "..."
}) but only call it when window.SocialShareButton exists and ensure cleanup
still clears the interval in all terminal cases.
In `@app/layout.js`:
- Around line 31-34: The external jsDelivr assets are missing SRI and
crossorigin attributes; update the <link> element that loads
"https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.css"
and the Next.js <Script> component that loads the matching .js to include
integrity="sha384-<calculated-hash>" and crossOrigin="anonymous". Generate the
SRI value by downloading each asset and computing the base64 sha384 digest (curl
-s <url> | sha384sum | xxd -r -p | base64) and plug that result into the
integrity attribute, keeping the same src and strategy props on the <Script>
component.
In `@README.md`:
- Around line 18-22: The README's Project Demo documents SocialShareButton but
references Issue `#19` (mobile navigation) — remove any auto-closing keywords or
issue-closing syntax and clarify linkage: in the "Project Demo" /
SocialShareButton note, replace any phrasing like "fixes `#19`" or "closes `#19`"
with "related to Issue `#19`" and add a short line that mobile navigation
(hamburger/menu accessibility) is not implemented here; also update the PR
description to avoid auto-closing Issue `#19` and explicitly state that the mobile
nav requirements remain outstanding. Ensure references point to
SocialShareButton and Issue `#19` (mobile navigation / hamburger/menu
accessibility) so reviewers can locate the discrepancy.
---
Nitpick comments:
In `@app/components/Layout/Footer/Footer.css`:
- Around line 73-86: The rule currently forces styles with multiple !important
flags and a debug comment; instead scope the selector to the mounting container
(e.g., use a parent id like `#share-button` .social-share-btn) and remove the
debug comment and all !important declarations so normal cascade and theming
work; update both the base selector (.social-share-btn) and the hover selector
(.social-share-btn:hover) to the scoped form and keep the same properties
(background, border, color, padding, border-radius, cursor, box-shadow) but
without !important.
🪄 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: 30ae8c1a-cbe5-4ad7-a27d-43d4fc44b018
📒 Files selected for processing (4)
README.mdapp/components/Layout/Footer/Footer.cssapp/components/Layout/Footer/index.jsxapp/layout.js
| useEffect(() => { | ||
| const interval = setInterval(() => { | ||
| if (typeof window !== "undefined" && window.SocialShareButton) { | ||
| new window.SocialShareButton({ | ||
| container: "#share-button", | ||
| url: "https://aossie.org", | ||
| title: "Check out AOSSIE!" | ||
| }); | ||
| clearInterval(interval); | ||
| } | ||
| }, 300); | ||
| return () => clearInterval(interval); | ||
| }, []); |
There was a problem hiding this comment.
Polling is unbounded if the external script never becomes available.
If window.SocialShareButton never loads, the interval keeps running for the component lifetime. Add a retry cap/timeout and fail fast.
Proposed reliability fix
useEffect(() => {
- const interval = setInterval(() => {
+ let attempts = 0;
+ const maxAttempts = 20; // ~6s at 300ms
+ const interval = setInterval(() => {
+ attempts += 1;
if (typeof window !== "undefined" && window.SocialShareButton) {
new window.SocialShareButton({
container: "#share-button",
url: "https://aossie.org",
title: "Check out AOSSIE!"
});
clearInterval(interval);
+ return;
}
+ if (attempts >= maxAttempts) clearInterval(interval);
}, 300);
return () => clearInterval(interval);
}, []);📝 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.
| useEffect(() => { | |
| const interval = setInterval(() => { | |
| if (typeof window !== "undefined" && window.SocialShareButton) { | |
| new window.SocialShareButton({ | |
| container: "#share-button", | |
| url: "https://aossie.org", | |
| title: "Check out AOSSIE!" | |
| }); | |
| clearInterval(interval); | |
| } | |
| }, 300); | |
| return () => clearInterval(interval); | |
| }, []); | |
| useEffect(() => { | |
| let attempts = 0; | |
| const maxAttempts = 20; // ~6s at 300ms | |
| const interval = setInterval(() => { | |
| attempts += 1; | |
| if (typeof window !== "undefined" && window.SocialShareButton) { | |
| new window.SocialShareButton({ | |
| container: "#share-button", | |
| url: "https://aossie.org", | |
| title: "Check out AOSSIE!" | |
| }); | |
| clearInterval(interval); | |
| return; | |
| } | |
| if (attempts >= maxAttempts) clearInterval(interval); | |
| }, 300); | |
| return () => clearInterval(interval); | |
| }, []); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/components/Layout/Footer/index.jsx` around lines 10 - 22, The useEffect
polling loop that creates new window.SocialShareButton (uses interval variable
inside useEffect) can run indefinitely if the external script never loads;
modify the effect to add a retry cap and a timeout: track attempts (e.g.,
maxAttempts) or an elapsed start time inside the effect, increment attempts each
tick and clearInterval(interval) and stop trying once the cap/time is reached,
and optionally log or show a failure; keep the existing creation code that
instantiates new window.SocialShareButton({ container: "#share-button", url:
"...", title: "..." }) but only call it when window.SocialShareButton exists and
ensure cleanup still clears the interval in all terminal cases.
| url: "https://aossie.org", | ||
| title: "Check out AOSSIE!" |
There was a problem hiding this comment.
Share payload is hardcoded to a different site.
The widget currently shares https://aossie.org instead of the active Resonate page. Use runtime page metadata (window.location.href, document.title) so shares reflect what the user is viewing.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/components/Layout/Footer/index.jsx` around lines 15 - 16, The share
payload in Layout/Footer/index.jsx currently hardcodes url: "https://aossie.org"
and title: "Check out AOSSIE!" so shares point to the wrong site; locate the
share payload object in the Footer component and replace those hardcoded values
with runtime page metadata (use window.location.href and document.title),
guarding for SSR by checking typeof window !== 'undefined' and falling back to
sensible defaults (e.g., site home URL and a default title) so the share uses
the current page URL and title when available.
| <link | ||
| rel="stylesheet" | ||
| href="https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.css" | ||
| /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
css_url="https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.css"
js_url="https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.js"
for url in "$css_url" "$js_url"; do
echo "URL: $url"
hash=$(curl -fsSL "$url" | openssl dgst -sha384 -binary | openssl base64 -A)
echo "integrity=\"sha384-$hash\""
echo
doneRepository: AOSSIE-Org/Resonate-Website
Length of output: 327
🏁 Script executed:
cat -n app/layout.js | sed -n '25,55p'Repository: AOSSIE-Org/Resonate-Website
Length of output: 905
🏁 Script executed:
# Search for all external CDN links in the layout file
rg 'href=|src=' app/layout.js -A 2 -B 1Repository: AOSSIE-Org/Resonate-Website
Length of output: 406
🏁 Script executed:
# Try to fetch the CSS/JS files and generate SRI using Python
python3 << 'EOF'
import hashlib
import base64
import urllib.request
urls = [
"https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.css",
"https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.js"
]
for url in urls:
try:
with urllib.request.urlopen(url, timeout=10) as response:
content = response.read()
hash_obj = hashlib.sha384(content)
integrity = "sha384-" + base64.b64encode(hash_obj.digest()).decode('ascii')
print(f"URL: {url}")
print(f'integrity="{integrity}"')
print()
except Exception as e:
print(f"Error fetching {url}: {e}")
print()
EOFRepository: AOSSIE-Org/Resonate-Website
Length of output: 555
🌐 Web query:
Next.js Script component integrity attribute SRI support
💡 Result:
The Next.js Script component (next/script) does not have a built-in integrity prop listed in the official documentation. Official docs for Script component props include src, strategy, onLoad, onReady, onError, etc., but no integrity. However, it supports additional arbitrary HTML attributes (like nonce, data-), which are forwarded to the underlying <script> element. You can manually add integrity="sha256-..." to external third-party scripts for SRI support. Next.js has experimental.sri support (next.config.js: experimental: { sri: { algorithm: 'sha256' } }) that automatically adds integrity attributes to its own internal static chunks (e.g., _next/static/chunks/) in App Router builds, generating a subresource-integrity-manifest.json. This works for Node.js and Edge runtimes but has limitations: missing for some client chunks ('use client'), stylesheets, and mismatches with CDN compression (open issues as of 2026). It does not apply to Script component-loaded third-party scripts. For complete SRI: - Manual for third-party via Script: <Script src="..." integrity="sha256-ABC123" crossorigin="anonymous" /> - Automatic (experimental, incomplete) for Next.js bundles via config.
Citations:
- 1: https://nextjs.org/docs/app/api-reference/components/script
- 2: https://nextjs.org/docs/app/guides/scripts
- 3: https://nextjs.org/docs/api-reference/next/script
- 4: https://nextjs.im/docs/14/pages/api-reference/components/script/
- 5: https://nextjs.org/docs/15/app/guides/scripts
- 6: [Feature request] Support for SRI vercel/next.js#23951
- 7: [SRI]
integritymissing for client chunks vercel/next.js#74147 - 8: experimental.sri: integrity mismatch blocks scripts when served via CDN/edge cache vercel/next.js#91633
- 9: Subresource Integrity (SRI) not working vercel/next.js#66901
- 10: https://nextjs.org/docs/app/api-reference/config/next-config-js
- 11: Add SRI support for Node.js Runtime vercel/next.js#73891
Add SRI integrity attributes to third-party CDN assets.
External CSS and JavaScript from jsdelivr are loaded without integrity verification, creating a supply-chain risk. Add integrity attributes (with corresponding SRI hash) and crossOrigin="anonymous" to both the <link> tag (lines 31-34) and the <Script> component (lines 43-46). The Next.js <Script> component supports arbitrary HTML attributes, so integrity can be passed directly:
Example for Script component
<Script
src="https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.js"
integrity="sha384-[hash-here]"
crossOrigin="anonymous"
strategy="afterInteractive"
/>Generate SRI hashes using: curl -s <url> | sha384sum | xxd -r -p | base64
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/layout.js` around lines 31 - 34, The external jsDelivr assets are missing
SRI and crossorigin attributes; update the <link> element that loads
"https://cdn.jsdelivr.net/gh/AOSSIE-Org/SocialShareButton@v1.0.3/src/social-share-button.css"
and the Next.js <Script> component that loads the matching .js to include
integrity="sha384-<calculated-hash>" and crossOrigin="anonymous". Generate the
SRI value by downloading each asset and computing the base64 sha384 digest (curl
-s <url> | sha384sum | xxd -r -p | base64) and plug that result into the
integrity attribute, keeping the same src and strategy props on the <Script>
component.
| ## 📺 Project Demo | ||
|
|
||
| Watch the Resonate Website in action with SocialShareButton: | ||
| [**Project Demo Video**](https://drive.google.com/file/d/12gu3D8wuIiDhwZvS12MaiEfg6CFZGTMv/view?usp=sharing) | ||
|
|
There was a problem hiding this comment.
PR closure target appears mismatched with linked issue objective.
This change documents SocialShareButton, but the linked Issue #19 objective is mobile navigation (hamburger/menu accessibility). Please avoid auto-closing that issue from this PR unless the nav requirements are implemented here.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@README.md` around lines 18 - 22, The README's Project Demo documents
SocialShareButton but references Issue `#19` (mobile navigation) — remove any
auto-closing keywords or issue-closing syntax and clarify linkage: in the
"Project Demo" / SocialShareButton note, replace any phrasing like "fixes `#19`"
or "closes `#19`" with "related to Issue `#19`" and add a short line that mobile
navigation (hamburger/menu accessibility) is not implemented here; also update
the PR description to avoid auto-closing Issue `#19` and explicitly state that the
mobile nav requirements remain outstanding. Ensure references point to
SocialShareButton and Issue `#19` (mobile navigation / hamburger/menu
accessibility) so reviewers can locate the discrepancy.
Tutorial: SocialShareButton Integration with Resonate Website
Closes #19 (AOSSIE-Org/SocialShareButton)
Added SocialShareButton to the Resonate landing page footer.
🎬 Demo Video: https://drive.google.com/file/d/12gu3D8wuIiDhwZvS12MaiEfg6CFZGTMv/view?usp=sharing
Summary by CodeRabbit
New Features
Documentation