From e5b1bda207226ce9ec7568bcbe22fc835c82f127 Mon Sep 17 00:00:00 2001 From: Nagajyothi-tammisetti Date: Sun, 17 May 2026 10:26:09 +0530 Subject: [PATCH 1/5] feat: add blog data schema following mentors.js pattern --- src/data/blog.js | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/data/blog.js diff --git a/src/data/blog.js b/src/data/blog.js new file mode 100644 index 0000000..5d9879d --- /dev/null +++ b/src/data/blog.js @@ -0,0 +1,49 @@ +const blogs = [ + { + id: 1, + title: "Breaking Into Tech: A Beginner's Roadmap for Women", + slug: "breaking-into-tech-beginners-roadmap", + author: "HerStack Team", + date: "2025-05-10", + readTime: "5 min read", + category: "Career", + tags: ["career", "beginners", "roadmap"], + excerpt: + "Feeling overwhelmed about where to start in tech? Here's a clear, step-by-step guide tailored for women entering the industry.", + content: + "Full article content goes here. This is placeholder text for now.", + coverImage: "/assets/blog/breaking-into-tech.jpg", + }, + { + id: 2, + title: "Top 10 Open Source Projects to Contribute to as a Beginner", + slug: "top-10-open-source-projects-for-beginners", + author: "HerStack Team", + date: "2025-05-15", + readTime: "7 min read", + category: "Open Source", + tags: ["open-source", "github", "beginners"], + excerpt: + "Contributing to open source is one of the best ways to grow your skills. Here are 10 beginner-friendly projects to get you started.", + content: + "Full article content goes here. This is placeholder text for now.", + coverImage: "/assets/blog/open-source.jpg", + }, + { + id: 3, + title: "How to Ace Your First Technical Interview", + slug: "how-to-ace-your-first-technical-interview", + author: "HerStack Team", + date: "2025-05-20", + readTime: "6 min read", + category: "Interview Prep", + tags: ["interview", "dsa", "career"], + excerpt: + "Technical interviews can be nerve-wracking. Here's everything you need to know to walk in confident and prepared.", + content: + "Full article content goes here. This is placeholder text for now.", + coverImage: "/assets/blog/technical-interview.jpg", + }, +]; + +export default blogs; \ No newline at end of file From 3ae3a426a7d669c38d8c6ff19583b4c625e42dd3 Mon Sep 17 00:00:00 2001 From: Nagajyothi-tammisetti Date: Sun, 17 May 2026 10:26:09 +0530 Subject: [PATCH 2/5] feat: add ShareButtons component (Twitter, LinkedIn, WhatsApp, CopyLink, native share) --- src/components/ShareButtons.jsx | 148 ++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/components/ShareButtons.jsx diff --git a/src/components/ShareButtons.jsx b/src/components/ShareButtons.jsx new file mode 100644 index 0000000..6f6cb96 --- /dev/null +++ b/src/components/ShareButtons.jsx @@ -0,0 +1,148 @@ +import { useState } from "react"; + +const ShareButtons = ({ title, url }) => { + const shareUrl = url || window.location.href; + const shareTitle = title || document.title; + const [copied, setCopied] = useState(false); + + const links = { + twitter: `https://twitter.com/intent/tweet?text=${encodeURIComponent( + shareTitle + )}&url=${encodeURIComponent(shareUrl)}`, + linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent( + shareUrl + )}`, + whatsapp: `https://api.whatsapp.com/send?text=${encodeURIComponent( + shareTitle + " " + shareUrl + )}`, + }; + + const handleNativeShare = async () => { + if (navigator.share) { + try { + await navigator.share({ title: shareTitle, url: shareUrl }); + } catch (err) { + // User cancelled or error — do nothing + } + } + }; + + const handleCopyLink = async () => { + try { + await navigator.clipboard.writeText(shareUrl); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch { + // Fallback for older browsers + const el = document.createElement("input"); + el.value = shareUrl; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + document.body.removeChild(el); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } + }; + + return ( +
+

+ Share this post +

+
+ {/* Twitter/X */} + + + + + Twitter / X + + + {/* LinkedIn */} + + + + + LinkedIn + + + {/* WhatsApp */} + + + + + WhatsApp + + + {/* Copy Link */} + + + {/* Native Share (mobile only) */} + {typeof navigator !== "undefined" && navigator.share && ( + + )} +
+ + {/* Toast notification */} + {copied && ( +
+ ✅ Link copied to clipboard! +
+ )} +
+ ); +}; + +export default ShareButtons; \ No newline at end of file From e79b1c1c15eaff48da7b0fdd4210bfd495d1aec9 Mon Sep 17 00:00:00 2001 From: Nagajyothi-tammisetti Date: Sun, 17 May 2026 10:26:10 +0530 Subject: [PATCH 3/5] feat: add BlogPostLayout component with ShareButtons at bottom --- src/components/BlogPostLayout.jsx | 76 +++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/components/BlogPostLayout.jsx diff --git a/src/components/BlogPostLayout.jsx b/src/components/BlogPostLayout.jsx new file mode 100644 index 0000000..497b2e8 --- /dev/null +++ b/src/components/BlogPostLayout.jsx @@ -0,0 +1,76 @@ +import ShareButtons from "./ShareButtons"; + +const BlogPostLayout = ({ post }) => { + const { + title, + author, + date, + readTime, + category, + tags = [], + content, + coverImage, + } = post; + + const formattedDate = new Date(date).toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + }); + + return ( +
+ {/* Category badge */} + + {category} + + + {/* Title */} +

+ {title} +

+ + {/* Meta row */} +
+ {author} + · + {formattedDate} + · + {readTime} +
+ + {/* Cover image */} + {coverImage && ( + {title} + )} + + {/* Tags */} + {tags.length > 0 && ( +
+ {tags.map((tag) => ( + + #{tag} + + ))} +
+ )} + + {/* Article body */} +
+

{content}

+
+ + {/* Share Buttons — placed at the bottom as per issue spec */} + +
+ ); +}; + +export default BlogPostLayout; \ No newline at end of file From c6d8f395a05840e844d3921b857f3841883e77d4 Mon Sep 17 00:00:00 2001 From: Nagajyothi-tammisetti Date: Sun, 17 May 2026 10:26:10 +0530 Subject: [PATCH 4/5] feat: add /blog and /blog/:slug routes to App --- src/App.jsx | 71 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 4504f55..8d07d9d 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,30 +1,45 @@ -import './styles/globals.css' -import Nav from './components/Nav' -import Hero from './components/Hero' -import Marquee from './components/Marquee' -import Pillars from './components/Pillars' -import LearningPath from './components/LearningPath' -import Storyboards from './components/Storyboards' -import Mentors from './components/Mentors' -import SummerOfAI from './components/SummerOfAI' -import Contribute from './components/Contribute' -import Footer from './components/Footer' +// Add these imports at the top of App.jsx +import { useState, useEffect } from "react"; +import { Routes, Route } from "react-router-dom"; +import BlogPostLayout from "./components/BlogPostLayout"; +import blogs from "./data/blog"; -export default function App() { +// --- Add this new component in the same file or a separate BlogPage.jsx --- +const BlogPage = () => { return ( - <> -