From ec0495f527deb88a0b126306f3d64ae8b6537f02 Mon Sep 17 00:00:00 2001 From: YourGitHubUsername Date: Tue, 19 Aug 2025 21:21:52 +0530 Subject: [PATCH 1/6] updated leaderboard in giveaway page --- src/pages/dashboard/giveaway/index.tsx | 571 ++++++++++++++++++++-- src/pages/dashboard/index.tsx | 124 ++--- src/pages/dashboard/leaderboard-page.css | 581 +++++++++++++++++++++++ 3 files changed, 1193 insertions(+), 83 deletions(-) create mode 100644 src/pages/dashboard/leaderboard-page.css diff --git a/src/pages/dashboard/giveaway/index.tsx b/src/pages/dashboard/giveaway/index.tsx index be38eb3d..32252f7e 100644 --- a/src/pages/dashboard/giveaway/index.tsx +++ b/src/pages/dashboard/giveaway/index.tsx @@ -1,26 +1,472 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import Layout from "@theme/Layout"; import Head from "@docusaurus/Head"; import { motion } from "framer-motion"; import SlotCounter from "react-slot-counter"; import NavbarIcon from "../../../components/navbar/NavbarIcon"; import { useHistory } from "@docusaurus/router"; +import { Home, MessageCircle, Gift, Trophy, Crown, Star, Award, Clock, Users, TrendingUp, Medal } from "lucide-react"; import "../dashboard.css"; +// Giveaway-specific styles +const giveawayStyles = ` +.giveaway-stats-banner { + display: flex; + justify-content: space-between; + gap: 0.75rem; + margin-bottom: 2rem; + padding: 0 1rem; +} + +.stat-item { + flex: 1; + display: flex; + align-items: center; + gap: 0.5rem; + background: var(--ifm-background-color); + border: 1px solid var(--ifm-color-emphasis-200); + border-radius: 8px; + padding: 0.5rem; + transition: all 0.3s ease; + box-shadow: 0 2px 8px var(--ifm-color-emphasis-200); +} + +.stat-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px var(--ifm-color-emphasis-300); +} + +.timer-icon { + background: linear-gradient(135deg, #ff6b6b, #ffa726) !important; +} + +.entries-icon { + background: linear-gradient(135deg, #4ecdc4, #44a08d) !important; +} + +.score-icon { + background: linear-gradient(135deg, #667eea, #764ba2) !important; +} + +.winners-icon { + background: linear-gradient(135deg, #f093fb, #f5576c) !important; +} + +.stat-icon { + width: 28px; + height: 28px; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.9rem; + flex-shrink: 0; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.stat-content { + min-width: 0; +} + +.stat-content h3 { + font-size: 0.65rem; + font-weight: 600; + color: var(--ifm-color-emphasis-700); + margin: 0 0 0.15rem 0; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.stat-value { + font-size: 1.1rem; + font-weight: 800; + color: var(--ifm-color-emphasis-900); + display: flex; + align-items: baseline; + gap: 0.15rem; + margin-bottom: 0.15rem; +} + +.stat-value span { + font-size: 0.6rem; + font-weight: 600; + color: var(--ifm-color-emphasis-600); +} + +.stat-content p { + font-size: 0.55rem; + color: var(--ifm-color-emphasis-500); + margin: 0; +} + +[data-theme='dark'] .stat-item { + background: var(--ifm-color-emphasis-100); + border-color: var(--ifm-color-emphasis-300); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); +} + +[data-theme='dark'] .stat-item:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); +} + +.giveaway-leaderboard-section { + margin: 3rem 0; + padding: 0 1rem; +} + +.giveaway-leaderboard-header { + text-align: center; + margin-bottom: 2rem; +} + +.giveaway-leaderboard-title { + font-size: 2.5rem; + font-weight: 800; + margin-bottom: 0.5rem; + color: var(--ifm-color-emphasis-900); +} + +.giveaway-leaderboard-subtitle { + font-size: 1.1rem; + color: var(--ifm-color-emphasis-700); + margin: 0; +} + +.giveaway-loading { + text-align: center; + padding: 3rem; + color: var(--ifm-color-emphasis-700); +} + +.giveaway-leaderboard-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1.5rem; + max-width: 1200px; + margin: 0 auto; +} + +.giveaway-leaderboard-card { + background: var(--ifm-background-color); + border: 1px solid var(--ifm-color-emphasis-300); + border-radius: 16px; + padding: 1.5rem; + position: relative; + overflow: hidden; + transition: all 0.3s ease; + box-shadow: 0 4px 12px var(--ifm-color-emphasis-200); +} + +.giveaway-leaderboard-card:hover { + box-shadow: 0 8px 25px var(--ifm-color-emphasis-300); + border-color: var(--ifm-color-primary); + transform: translateY(-2px); +} + +.giveaway-leaderboard-card.rank-1 { + background: linear-gradient(135deg, #ffd700, #ffed4e); + border-color: #ffd700; +} + +.giveaway-leaderboard-card.rank-2 { + background: linear-gradient(135deg, #c0c0c0, #e8e8e8); + border-color: #c0c0c0; +} + +.giveaway-leaderboard-card.rank-3 { + background: linear-gradient(135deg, #cd7f32, #daa520); + border-color: #cd7f32; +} + +[data-theme='dark'] .giveaway-leaderboard-card { + background: var(--ifm-color-emphasis-100); + border-color: var(--ifm-color-emphasis-400); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +[data-theme='dark'] .giveaway-leaderboard-card:hover { + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4); +} + +[data-theme='dark'] .giveaway-leaderboard-card.rank-1 { + background: linear-gradient(135deg, #b8860b, #daa520); +} + +[data-theme='dark'] .giveaway-leaderboard-card.rank-2 { + background: linear-gradient(135deg, #708090, #a9a9a9); +} + +[data-theme='dark'] .giveaway-leaderboard-card.rank-3 { + background: linear-gradient(135deg, #8b4513, #cd853f); +} + +.giveaway-rank-badge { + position: absolute; + top: 1rem; + right: 1rem; + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + font-size: 0.9rem; + background: var(--ifm-color-primary); + color: var(--ifm-color-primary-contrast-background); +} + +.giveaway-avatar { + position: relative; + width: 80px; + height: 80px; + margin: 0 auto 1rem; +} + +.giveaway-avatar img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; + border: 3px solid var(--ifm-color-primary); +} + +.giveaway-badge { + position: absolute; + bottom: -5px; + left: 50%; + transform: translateX(-50%); + background: var(--ifm-color-primary); + color: var(--ifm-color-primary-contrast-background); + padding: 0.25rem 0.5rem; + border-radius: 12px; + font-size: 0.7rem; + font-weight: 600; + white-space: nowrap; +} + +.giveaway-info { + text-align: center; + margin-bottom: 1rem; +} + +.giveaway-name { + font-size: 1.2rem; + font-weight: 700; + margin-bottom: 0.5rem; + color: var(--ifm-color-emphasis-900); +} + +.giveaway-leaderboard-card.rank-1 .giveaway-name, +.giveaway-leaderboard-card.rank-2 .giveaway-name, +.giveaway-leaderboard-card.rank-3 .giveaway-name { + color: var(--ifm-color-emphasis-1000); +} + +.giveaway-stats { + display: flex; + justify-content: space-around; + gap: 1rem; +} + +.giveaway-stat { + text-align: center; +} + +.giveaway-stat .stat-value { + display: block; + font-size: 1.5rem; + font-weight: 700; + color: var(--ifm-color-primary); +} + +.giveaway-leaderboard-card.rank-1 .stat-value, +.giveaway-leaderboard-card.rank-2 .stat-value, +.giveaway-leaderboard-card.rank-3 .stat-value { + color: var(--ifm-color-emphasis-1000); +} + +.giveaway-stat .stat-label { + font-size: 0.8rem; + color: var(--ifm-color-emphasis-600); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.giveaway-leaderboard-card.rank-1 .stat-label, +.giveaway-leaderboard-card.rank-2 .stat-label, +.giveaway-leaderboard-card.rank-3 .stat-label { + color: var(--ifm-color-emphasis-800); +} + +.giveaway-profile-btn { + display: block; + width: 100%; + padding: 0.75rem; + background: var(--ifm-color-primary); + color: var(--ifm-color-primary-contrast-background); + text-decoration: none; + border-radius: 8px; + text-align: center; + font-weight: 600; + transition: all 0.3s ease; +} + +.giveaway-profile-btn:hover { + background: var(--ifm-color-primary-dark); + color: var(--ifm-color-primary-contrast-background); + text-decoration: none; + transform: translateY(-2px); +} + +.giveaway-leaderboard-card.rank-1 .giveaway-profile-btn, +.giveaway-leaderboard-card.rank-2 .giveaway-profile-btn, +.giveaway-leaderboard-card.rank-3 .giveaway-profile-btn { + background: var(--ifm-color-emphasis-800); + color: var(--ifm-color-emphasis-0); +} + +.giveaway-leaderboard-card.rank-1 .giveaway-profile-btn:hover, +.giveaway-leaderboard-card.rank-2 .giveaway-profile-btn:hover, +.giveaway-leaderboard-card.rank-3 .giveaway-profile-btn:hover { + background: var(--ifm-color-emphasis-900); + color: var(--ifm-color-emphasis-0); +} + +@media (max-width: 768px) { + .giveaway-stats-banner { + flex-direction: column; + gap: 0.5rem; + } + + .stat-item { + padding: 0.4rem; + } + + .stat-icon { + width: 24px; + height: 24px; + font-size: 0.8rem; + } + + .stat-value { + font-size: 1rem; + } + + .stat-content h3 { + font-size: 0.6rem; + } + + .stat-content p { + font-size: 0.5rem; + } + + .giveaway-leaderboard-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .giveaway-leaderboard-title { + font-size: 2rem; + } +} +`; + +// Inject styles +if (typeof document !== 'undefined') { + const existingStyle = document.getElementById('giveaway-styles'); + if (!existingStyle) { + const styleSheet = document.createElement('style'); + styleSheet.id = 'giveaway-styles'; + styleSheet.textContent = giveawayStyles; + document.head.appendChild(styleSheet); + } +} + +interface GiveawayEntry { + rank: number; + name: string; + avatar: string; + points: number; + contributions: number; + github_url: string; + badge?: string; +} + const GiveawayPage: React.FC = () => { const history = useHistory(); const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false); + const [leaderboard, setLeaderboard] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Simulate fetching leaderboard data + const fetchLeaderboard = async () => { + setLoading(true); + // Simulate API delay + await new Promise(resolve => setTimeout(resolve, 1000)); + + const mockData: GiveawayEntry[] = [ + { + rank: 1, + name: "sanjay-kv", + avatar: "https://avatars.githubusercontent.com/u/30715153?v=4", + points: 2500, + contributions: 45, + github_url: "https://github.com/sanjay-kv", + badge: "🏆 Champion" + }, + { + rank: 2, + name: "vansh-codes", + avatar: "https://avatars.githubusercontent.com/u/114163734?v=4", + points: 2100, + contributions: 38, + github_url: "https://github.com/vansh-codes", + badge: "🥈 Runner-up" + }, + { + rank: 3, + name: "Hemu21", + avatar: "https://avatars.githubusercontent.com/u/106808387?v=4", + points: 1850, + contributions: 32, + github_url: "https://github.com/Hemu21", + badge: "🥉 Third Place" + }, + { + rank: 4, + name: "contributor4", + avatar: "https://avatars.githubusercontent.com/u/1?v=4", + points: 1600, + contributions: 28, + github_url: "https://github.com/contributor4" + }, + { + rank: 5, + name: "contributor5", + avatar: "https://avatars.githubusercontent.com/u/2?v=4", + points: 1400, + contributions: 24, + github_url: "https://github.com/contributor5" + } + ]; + + setLeaderboard(mockData); + setLoading(false); + }; + + fetchLeaderboard(); + }, []); const handleTabChange = ( - tab: "home" | "discuss" | "leaderboard" | "contributors" | "giveaway" + tab: "home" | "discuss" | "leaderboard" | "giveaway" ) => { setIsMobileSidebarOpen(false); if (tab === "discuss") { history.push("/dashboard#discuss"); } else if (tab === "leaderboard") { - history.push("/dashboard#leaderboard"); - } else if (tab === "contributors") { history.push("/dashboard#contributors"); } else if (tab === "home") { history.push("/dashboard"); @@ -58,7 +504,7 @@ const GiveawayPage: React.FC = () => { ); return ( - + 🎁 RecodeHive Giveaway @@ -97,39 +543,30 @@ const GiveawayPage: React.FC = () => {
  • handleTabChange("home")}> - + Home
  • handleTabChange("discuss")}> - + Discuss
  • -
  • handleTabChange("leaderboard")} - > - - - - Leaderboard -
  • - + Giveaway
  • handleTabChange("contributors")} + onClick={() => handleTabChange("leaderboard")} > - + - Contributors + Leaderboard
@@ -185,26 +622,104 @@ const GiveawayPage: React.FC = () => {
+ + {/* Giveaway Leaderboard */} + +
+

+ 🎁 Giveaway Leaderboard +

+

+ Top contributors competing for amazing prizes! +

+
+ + {loading ? ( +
+
Loading...
+

Fetching leaderboard data...

+
+ ) : ( +
+ {leaderboard.map((entry, index) => ( + +
+ {entry.rank <= 3 ? ( + entry.rank === 1 ? : + entry.rank === 2 ? : + + ) : ( + `#${entry.rank}` + )} +
+ +
+ {entry.name} + {entry.badge && ( +
{entry.badge}
+ )} +
+ +
+

{entry.name}

+
+
+ {entry.points} + Points +
+
+ {entry.contributions} + Contributions +
+
+
+ + + View Profile + +
+ ))} +
+ )} +
diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 5ed2dc0d..af151567 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -90,7 +90,7 @@ const DashboardContent: React.FC = () => { const location = useLocation(); const history = useHistory(); const [activeTab, setActiveTab] = useState< - "home" | "discuss" | "leaderboard" | "giveaway" | "contributors" + "home" | "discuss" | "giveaway" | "contributors" >("home"); // Discussion state management @@ -143,8 +143,6 @@ const DashboardContent: React.FC = () => { // Set active tab based on URL hash if (location.hash === "#discuss") { setActiveTab("discuss"); - } else if (location.hash === "#leaderboard") { - setActiveTab("leaderboard"); } else if (location.hash === "#contributors") { setActiveTab("contributors"); } else if (location.hash === "#giveaway") { @@ -177,13 +175,70 @@ const DashboardContent: React.FC = () => { } }; - // Fetch leaderboard data when leaderboard or contributors tab is active + // Fetch leaderboard data when contributors tab is active or on initial load useEffect(() => { - if (activeTab === "leaderboard" || activeTab === "contributors") { + if (activeTab === "contributors") { fetchLeaderboardData(); } }, [activeTab]); + // Load initial demo data if no data exists + useEffect(() => { + if (leaderboardData.length === 0) { + const initialData: LeaderboardEntry[] = [ + { + rank: 1, + name: "sanjay-kv", + username: "sanjay-kv", + avatar: "https://avatars.githubusercontent.com/u/30715153?v=4", + contributions: 250, + repositories: 25, + score: 2500, + achievements: ["Top Contributor", "Founder", "Maintainer"], + github_url: "https://github.com/sanjay-kv", + streak: 15, + postManTag: false, + web3hack: false, + weeklyContributions: 35, + monthlyContributions: 120, + }, + { + rank: 2, + name: "vansh-codes", + username: "vansh-codes", + avatar: "https://avatars.githubusercontent.com/u/114163734?v=4", + contributions: 180, + repositories: 22, + score: 1800, + achievements: ["Rising Star", "Active Contributor", "Star Contributor"], + github_url: "https://github.com/vansh-codes", + streak: 8, + postManTag: false, + web3hack: false, + weeklyContributions: 25, + monthlyContributions: 85, + }, + { + rank: 3, + name: "Hemu21", + username: "Hemu21", + avatar: "https://avatars.githubusercontent.com/u/106808387?v=4", + contributions: 120, + repositories: 18, + score: 1200, + achievements: ["Power User", "Star Contributor", "Consistent"], + github_url: "https://github.com/Hemu21", + streak: 5, + postManTag: false, + web3hack: false, + weeklyContributions: 18, + monthlyContributions: 60, + }, + ]; + setLeaderboardData(initialData); + } + }, []); + // Discussion handlers const handleDiscussionTabChange = (tab: DiscussionTab) => { setActiveDiscussionTab(tab); @@ -675,7 +730,7 @@ const DashboardContent: React.FC = () => { }; const handleTabChange = ( - tab: "home" | "discuss" | "leaderboard" | "giveaway" | "contributors" + tab: "home" | "discuss" | "giveaway" | "contributors" ) => { setActiveTab(tab); setIsMobileSidebarOpen(false); // Close mobile sidebar @@ -683,9 +738,6 @@ const DashboardContent: React.FC = () => { if (tab === "discuss") { history.push("#discuss"); window.scrollTo(0, 0); - } else if (tab === "leaderboard") { - history.push("#leaderboard"); - window.scrollTo(0, 0); } else if (tab === "giveaway") { history.push("/dashboard/giveaway"); } else if (tab === "contributors") { @@ -981,20 +1033,7 @@ const DashboardContent: React.FC = () => { Discuss -
{ - handleTabChange("leaderboard"); - setShowDashboardMenu(false); - }} - > - - - - Leaderboard -
+
{ @@ -1017,9 +1056,9 @@ const DashboardContent: React.FC = () => { }} > - + - Contributors + Leaderboard
@@ -1063,17 +1102,7 @@ const DashboardContent: React.FC = () => { Discuss -
  • handleTabChange("leaderboard")} - > - - - - Leaderboard -
  • +
  • handleTabChange("giveaway")} @@ -1090,9 +1119,9 @@ const DashboardContent: React.FC = () => { onClick={() => handleTabChange("contributors")} > - + - Contributors + Leaderboard
  • @@ -1114,22 +1143,7 @@ const DashboardContent: React.FC = () => { } ${isSidebarCollapsed ? "sidebar-collapsed" : ""}`} onClick={() => isSidebarCollapsed && setIsSidebarCollapsed(false)} > - {activeTab === "leaderboard" ? ( - /* Leaderboard Tab */ - -
    -

    - RecodeHive Leaderboard -

    -

    Coming soon...

    -
    -
    - ) : activeTab === "home" ? ( + {activeTab === "home" ? ( // Home tab content
    { transition={{ duration: 0.6 }} >

    - RecodeHive Contributors + RecodeHive Leaderboard

    Live rankings from RecodeHive GitHub Organization • Updated diff --git a/src/pages/dashboard/leaderboard-page.css b/src/pages/dashboard/leaderboard-page.css new file mode 100644 index 00000000..3d8a7ad3 --- /dev/null +++ b/src/pages/dashboard/leaderboard-page.css @@ -0,0 +1,581 @@ +/* ===== MODERN LEADERBOARD PAGE STYLING ===== */ + +.leaderboard-page { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; + min-height: 100vh; +} + +.leaderboard-page-header { + text-align: center; + margin-bottom: 3rem; + padding: 3rem 2rem; + background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); + border-radius: 24px; + position: relative; + overflow: hidden; + box-shadow: 0 12px 40px rgba(102, 126, 234, 0.3); +} + +[data-theme="dark"] .leaderboard-page-header { + background: linear-gradient(135deg, #4c63d2 0%, #5a4b8c 50%, #d084e0 100%); + box-shadow: 0 12px 40px rgba(76, 99, 210, 0.4); +} + +.leaderboard-page-title { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + font-size: 3.5rem; + font-weight: 800; + margin-bottom: 1rem; + color: #ffffff; + text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); +} + +.leaderboard-page-title .highlight { + background: linear-gradient(135deg, #ffd700, #ffed4e); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + filter: drop-shadow(0 2px 4px rgba(255, 215, 0, 0.3)); +} + +.leaderboard-page-subtitle { + color: rgba(255, 255, 255, 0.95); + font-size: 1.2rem; + margin-bottom: 2rem; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); +} + +.filter-section { + display: flex; + justify-content: center; + margin-bottom: 2rem; +} + +.filter-buttons { + display: flex; + gap: 0.5rem; + background: var(--ifm-card-background-color); + padding: 0.5rem; + border-radius: 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + border: 1px solid var(--ifm-color-emphasis-200); +} + +[data-theme="dark"] .filter-buttons { + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-300); +} + +.filter-btn { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + border: none; + border-radius: 15px; + background: transparent; + color: var(--ifm-color-emphasis-700); + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + font-size: 0.9rem; +} + +.filter-btn:hover { + background: var(--ifm-color-emphasis-100); + color: var(--ifm-color-emphasis-900); +} + +.filter-btn.active { + background: linear-gradient(135deg, var(--ifm-color-primary), var(--ifm-color-primary-dark)); + color: white; + box-shadow: 0 4px 15px rgba(var(--ifm-color-primary-rgb), 0.3); +} + +.filter-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.stats-summary { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; + margin-bottom: 3rem; +} + +.stat-card { + display: flex; + align-items: center; + gap: 1rem; + padding: 1.5rem; + background: var(--ifm-card-background-color); + border-radius: 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + border: 1px solid var(--ifm-color-emphasis-200); + transition: all 0.3s ease; +} + +[data-theme="dark"] .stat-card { + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-300); +} + +.stat-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); +} + +.stat-icon { + display: flex; + align-items: center; + justify-content: center; + width: 50px; + height: 50px; + border-radius: 15px; + background: linear-gradient(135deg, var(--ifm-color-primary), var(--ifm-color-primary-dark)); + color: white; +} + +.stat-info { + flex: 1; +} + +.stat-value { + font-size: 2rem; + font-weight: 800; + color: var(--ifm-color-emphasis-900); + line-height: 1; +} + +.stat-label { + font-size: 0.9rem; + color: var(--ifm-color-emphasis-600); + margin-top: 0.25rem; +} + +.leaderboard-table-wrapper { + background: var(--ifm-card-background-color); + border-radius: 24px; + overflow: hidden; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); + border: 1px solid var(--ifm-color-emphasis-200); +} + +[data-theme="dark"] .leaderboard-table-wrapper { + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-300); +} + +.leaderboard-table { + width: 100%; +} + +.leaderboard-table-header { + display: grid; + grid-template-columns: 100px 1fr 140px 120px; + background: var(--ifm-color-emphasis-100); + padding: 1.25rem 1.5rem; + font-weight: 700; + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.8px; + color: var(--ifm-color-emphasis-800); + border-bottom: 2px solid var(--ifm-color-emphasis-200); +} + +[data-theme="dark"] .leaderboard-table-header { + background: var(--ifm-color-emphasis-200); + color: var(--ifm-color-emphasis-600); +} + +.leaderboard-header-cell { + display: flex; + align-items: center; + justify-content: center; +} + +.leaderboard-header-cell.username-header { + justify-content: flex-start; +} + +.leaderboard-table-body { + display: flex; + flex-direction: column; +} + +.leaderboard-row { + display: grid; + grid-template-columns: 100px 1fr 140px 120px; + padding: 1.75rem 1.5rem; + border-bottom: 1px solid var(--ifm-color-emphasis-200); + transition: all 0.3s ease; + position: relative; +} + +[data-theme="dark"] .leaderboard-row { + border-bottom: 1px solid var(--ifm-color-emphasis-300); +} + +.leaderboard-row:hover { + background: var(--ifm-color-emphasis-100); + transform: translateX(3px); +} + +[data-theme="dark"] .leaderboard-row:hover { + background: var(--ifm-color-emphasis-200); +} + +.leaderboard-row:last-child { + border-bottom: none; +} + +.leaderboard-row.top-1 { + background: linear-gradient(135deg, rgba(255, 215, 0, 0.12) 0%, rgba(255, 193, 7, 0.04) 100%); + border-left: 4px solid #ffd700; +} + +.leaderboard-row.top-2 { + background: linear-gradient(135deg, rgba(192, 192, 192, 0.12) 0%, rgba(169, 169, 169, 0.04) 100%); + border-left: 4px solid #c0c0c0; +} + +.leaderboard-row.top-3 { + background: linear-gradient(135deg, rgba(205, 127, 50, 0.12) 0%, rgba(184, 134, 11, 0.04) 100%); + border-left: 4px solid #cd7f32; +} + +.leaderboard-cell { + display: flex; + align-items: center; + justify-content: center; +} + +.leaderboard-rank-cell { + justify-content: center; +} + +.leaderboard-rank-badge { + display: flex; + align-items: center; + justify-content: center; + width: 50px; + height: 50px; + border-radius: 50%; + font-weight: 700; + background: var(--ifm-color-emphasis-200); + color: var(--ifm-color-emphasis-800); + transition: all 0.3s ease; +} + +.leaderboard-rank-badge.rank-1 { + background: linear-gradient(135deg, #ffd700, #ffed4e); + color: #1a1a1a; + box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4); + transform: scale(1.1); +} + +.leaderboard-rank-badge.rank-2 { + background: linear-gradient(135deg, #c0c0c0, #e8e8e8); + color: #1a1a1a; + box-shadow: 0 6px 20px rgba(192, 192, 192, 0.4); + transform: scale(1.05); +} + +.leaderboard-rank-badge.rank-3 { + background: linear-gradient(135deg, #cd7f32, #daa520); + color: #ffffff; + box-shadow: 0 6px 20px rgba(205, 127, 50, 0.4); +} + +.leaderboard-user-cell { + justify-content: flex-start; +} + +.leaderboard-user-info { + display: flex; + align-items: center; + gap: 1rem; +} + +.leaderboard-user-avatar { + width: 48px; + height: 48px; + border-radius: 50%; + border: 3px solid var(--ifm-color-primary-light); + object-fit: cover; + transition: all 0.3s ease; +} + +.leaderboard-user-avatar:hover { + transform: scale(1.1); + border-color: var(--ifm-color-primary); +} + +.leaderboard-user-details { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.leaderboard-username { + font-weight: 600; + color: var(--ifm-color-emphasis-900); + font-size: 1rem; +} + +.leaderboard-user-achievements { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; +} + +.leaderboard-achievement-badge { + background: var(--ifm-color-primary); + color: white; + padding: 0.2rem 0.6rem; + border-radius: 12px; + font-size: 0.65rem; + font-weight: 600; +} + +.leaderboard-points-cell { + flex-direction: column; + gap: 0.25rem; +} + +.leaderboard-points-value { + font-size: 1.75rem; + font-weight: 800; + color: var(--ifm-color-primary); +} + +.leaderboard-points-label { + font-size: 0.8rem; + color: var(--ifm-color-emphasis-600); +} + +.streak-indicator { + display: flex; + align-items: center; + gap: 0.25rem; + font-size: 0.7rem; + color: var(--ifm-color-warning); + margin-top: 0.25rem; +} + +.leaderboard-date-cell { + justify-content: center; +} + +.leaderboard-date-value { + font-size: 0.9rem; + color: var(--ifm-color-emphasis-700); + font-weight: 500; +} + +.leaderboard-cta { + margin-top: 4rem; + text-align: center; + padding: 3rem 2rem; + background: linear-gradient(135deg, var(--ifm-color-primary) 0%, var(--ifm-color-primary-dark) 100%); + border-radius: 24px; + color: white; +} + +.cta-content h3 { + font-size: 2rem; + font-weight: 700; + margin-bottom: 1rem; + color: white; +} + +.cta-content p { + font-size: 1.1rem; + margin-bottom: 2rem; + opacity: 0.9; + max-width: 600px; + margin-left: auto; + margin-right: auto; +} + +.cta-buttons { + display: flex; + gap: 1rem; + justify-content: center; + flex-wrap: wrap; +} + +.cta-primary, +.cta-secondary { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.875rem 1.75rem; + border-radius: 25px; + font-weight: 600; + text-decoration: none; + transition: all 0.3s ease; +} + +.cta-primary { + background: rgba(255, 255, 255, 0.2); + color: white; + border: 2px solid rgba(255, 255, 255, 0.3); +} + +.cta-primary:hover { + background: rgba(255, 255, 255, 0.3); + transform: translateY(-2px); + color: white; + text-decoration: none; +} + +.cta-secondary { + background: transparent; + color: white; + border: 2px solid rgba(255, 255, 255, 0.5); +} + +.cta-secondary:hover { + background: rgba(255, 255, 255, 0.1); + transform: translateY(-2px); + color: white; + text-decoration: none; +} + +.error-message { + background: linear-gradient(135deg, #fee2e2, #fecaca); + border: 1px solid #fca5a5; + border-radius: 16px; + padding: 1.5rem; + margin-bottom: 2rem; + text-align: center; +} + +[data-theme="dark"] .error-message { + background: linear-gradient(135deg, #7f1d1d, #991b1b); + border: 1px solid #dc2626; + color: #fecaca; +} + +.error-content h3 { + color: #dc2626; + margin-bottom: 0.5rem; +} + +[data-theme="dark"] .error-content h3 { + color: #fca5a5; +} + +.error-note { + font-size: 0.9rem; + opacity: 0.8; + margin-top: 0.5rem; +} + +.leaderboard-loading { + text-align: center; + padding: 4rem 2rem; + background: var(--ifm-card-background-color); + border-radius: 24px; + border: 1px solid var(--ifm-color-emphasis-200); +} + +[data-theme="dark"] .leaderboard-loading { + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-color-emphasis-300); +} + +.leaderboard-loading-spinner { + width: 48px; + height: 48px; + border: 4px solid var(--ifm-color-emphasis-300); + border-top: 4px solid var(--ifm-color-primary); + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto 1rem; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Responsive Design */ +@media (max-width: 768px) { + .leaderboard-page { + padding: 1rem; + } + + .leaderboard-page-title { + font-size: 2.5rem; + flex-direction: column; + gap: 0.5rem; + } + + .stats-summary { + grid-template-columns: 1fr; + gap: 1rem; + } + + .leaderboard-table-header, + .leaderboard-row { + grid-template-columns: 60px 1fr 80px; + padding: 1rem 0.75rem; + } + + .leaderboard-date-cell, + .leaderboard-header-cell:last-child { + display: none; + } + + .leaderboard-user-info { + gap: 0.75rem; + } + + .leaderboard-user-avatar { + width: 40px; + height: 40px; + } + + .leaderboard-points-value { + font-size: 1.5rem; + } +} + +@media (max-width: 480px) { + .leaderboard-page-header { + padding: 2rem 1rem; + } + + .leaderboard-page-title { + font-size: 2rem; + } + + .filter-buttons { + flex-direction: column; + width: 100%; + } + + .filter-btn { + justify-content: center; + } + + .cta-buttons { + flex-direction: column; + align-items: center; + } + + .cta-primary, + .cta-secondary { + width: 100%; + max-width: 300px; + justify-content: center; + } +} \ No newline at end of file From b14f3568e44fc3b39ed54ac891db301788a1e654 Mon Sep 17 00:00:00 2001 From: YourGitHubUsername Date: Tue, 19 Aug 2025 21:33:54 +0530 Subject: [PATCH 2/6] updated --- src/pages/dashboard/index.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index af151567..cc1c9470 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -24,6 +24,7 @@ import { TrendingUp, Home, Trophy, + Users, Gift, Calendar, BarChart3, @@ -829,7 +830,7 @@ const DashboardContent: React.FC = () => { >

    GitHub API Rate Limit Reached

    - We've temporarily reached the GitHub API rate limit. The leaderboard + We've temporarily reached the GitHub API rate limit. The contributors page will automatically refresh when the limit resets.

    {retryTimer && ( @@ -1056,9 +1057,9 @@ const DashboardContent: React.FC = () => { }} > - + - Leaderboard + Contributors
    @@ -1119,9 +1120,9 @@ const DashboardContent: React.FC = () => { onClick={() => handleTabChange("contributors")} > - + - Leaderboard + Contributors
    @@ -1213,7 +1214,7 @@ const DashboardContent: React.FC = () => { >

    - Top Contributors Leaderboard + Top Contributors Board

    Celebrating our most active community members who make @@ -1544,7 +1545,7 @@ const DashboardContent: React.FC = () => { transition={{ duration: 0.6 }} >

    - RecodeHive Leaderboard + RecodeHive Contributors

    Live rankings from RecodeHive GitHub Organization • Updated @@ -1619,7 +1620,7 @@ const DashboardContent: React.FC = () => { )}

    - Showing cached data below. The leaderboard will + Showing cached data below. The contributors page will automatically refresh when possible.

    From 0e41b8ac05c9e458c9d04cec6d90eaaa2d590313 Mon Sep 17 00:00:00 2001 From: YourGitHubUsername Date: Wed, 20 Aug 2025 23:57:11 +0530 Subject: [PATCH 3/6] used mockup for project section --- blog/spark-architecture/index.md | 319 +++++++++++++++++---- src/components/mockup/DeveloperMockup.tsx | 209 ++++++++++++++ src/components/ourProjects.tsx | 327 ++++++++++++++++++++-- src/database/blogs/index.tsx | 4 +- 4 files changed, 778 insertions(+), 81 deletions(-) create mode 100644 src/components/mockup/DeveloperMockup.tsx diff --git a/blog/spark-architecture/index.md b/blog/spark-architecture/index.md index 454946c5..92338b86 100644 --- a/blog/spark-architecture/index.md +++ b/blog/spark-architecture/index.md @@ -1,106 +1,309 @@ --- title: "Spark Architecture Explained" -sidebar_label: Spark Architecture Explanation -authors: [Aditya-Singh-Rathore, sanjay-kv] -tags: [spark, azure, design] +authors: [Aditya-Singh-Rathore] +tags: [Apache Spark, Spark Architecture, Big Data, Distributed Computing, Data Engineering] date: 2025-08-18 -hide_table_of_contents: true + +description: Apache Spark is a fast, open-source big data framework that leverages in-memory computing for high performance. Its architecture powers scalable distributed processing across clusters, making it essential for analytics and machine learning. + +draft: false +canonical_url: +# meta: +# - name: "robots" +# content: "index, follow" +# - property: "og:title" +# content: "What is Google DeepMind AI?" +# - property: "og:description" +# content: "DeepMind is an auxiliary of Google that centers around man-made brainpower. All the more explicitly, it utilizes a part of AI called AI" +# - property: "og:type" +# content: "article" +# - property: "og:url" +# content: "/blog/getting-started-with-mern" +# - property: "og:image" +# content: "/assets/images/mern-8a27add30515e58f789f89a4c9072818.jpg" +# - name: "twitter:card" +# content: "summary_large_image" +# - name: "twitter:title" +# content: "A Comprehensive Guide to Get You Started with MERN Stack" +# - name: "twitter:description" +# content: "DeepMind is an auxiliary of Google that centers around man-made brainpower. All the more explicitly, it utilizes a part of AI called AI" +# - name: "twitter:image" +# content: "assets/images/mern-8a27add30515e58f789f89a4c9072818.jpg" + --- -Hey there, fellow data enthusiasts! 👋 Add a comment on lines R37 to R39Add diff commentMarkdown input: edit mode selected.WritePreviewAdd a suggestionHeadingBoldItalicQuoteCodeLinkUnordered listNumbered listTask listMentionReferenceSaved repliesAdd FilesPaste, drop, or click to add filesCancelCommentStart a reviewReturn to code + +# Understanding Apache Spark Architecture: A Deep Dive into Distributed Computing + +Hey there, fellow data enthusiasts! 👋 I remember the first time I encountered a Spark architecture diagram. It looked like a complex web of boxes and arrows that seemed to communicate in some secret distributed computing language. But once I understood what each component actually does and how they work together, everything clicked into place. Today, I want to walk you through Spark's architecture in a way that I wish someone had explained it to me back then - focusing on the core components and how this beautiful system actually works under the hood. -### 👤 Research the User -When you’re designing a new product, it’s important to remember to research your user. This means gathering data about who will be using the product and their needs. Who are they? What do they need? What are their habits and preferences? What are their goals? What are their pain points? What are they looking for in a product? Only by understanding the user can you create a product that meets their needs and exceeds their expectations. If you design a product without understanding the user, it is likely to be unsuccessful. +## What is Apache Spark? + +Before diving into the architecture, let's establish what we're dealing with. Apache Spark is an open-source, distributed computing framework designed to process massive datasets across clusters of computers. Think of it as a coordinator that can take your data processing job and intelligently distribute it across multiple machines to get the work done faster. + +The key insight that makes Spark special? It keeps data in memory between operations whenever possible, which is why it can be dramatically faster than traditional batch processing systems. + +## The Big Picture: High-Level Architecture + +![Spark Architecture](/img/blogs/07-spark_architecture.png) + + +When you look at Spark's architecture, you're essentially looking at a well-orchestrated system with three main types of components working together: + +1. **Driver Program** - The mastermind that coordinates everything +2. **Cluster Manager** - The resource allocator +3. **Executors** - The workers that do the actual processing + +Let's break down each of these and understand how they collaborate. + +## Core Components Deep Dive + +### 1. The Driver Program: Your Application's Brain + +The Driver Program is where your Spark application begins and ends. When you write a Spark program and run it, you're essentially creating a driver program. Here's what makes it the brain of the operation: + +**What the Driver Does:** +- Contains your main() function and defines RDDs and operations on them +- Converts your high-level operations into a DAG (Directed Acyclic Graph) of tasks +- Schedules tasks across the cluster +- Coordinates with the cluster manager to get resources +- Collects results from executors and returns final results + +**Think of it this way:** If your Spark application were a restaurant, the Driver would be the head chef who takes orders (your code), breaks them down into specific cooking tasks, assigns those tasks to kitchen staff (executors), and ensures everything comes together for the final dish. + +The driver runs in its own JVM process and maintains all the metadata about your Spark application throughout its lifetime. + +### 2. Cluster Manager: The Resource Referee + +The Cluster Manager sits between your driver and the actual compute resources. Its job is to allocate and manage resources across the cluster. Spark is flexible and works with several cluster managers: + +**Standalone Cluster Manager:** +- Spark's built-in cluster manager +- Simple to set up and understand +- Great for dedicated Spark clusters + +**Apache YARN (Yet Another Resource Negotiator):** +- Hadoop's resource manager +- Perfect if you're in a Hadoop ecosystem +- Allows resource sharing between Spark and other Hadoop applications + +**Apache Mesos:** +- A general-purpose cluster manager +- Can handle multiple frameworks beyond just Spark +- Good for mixed workload environments + +**Kubernetes:** +- The modern container orchestration platform +- Increasingly popular for new deployments +- Excellent for cloud-native environments + +**The key point:** The cluster manager's job is resource allocation - it doesn't care what your application does, just how much CPU and memory it needs. + +### 3. Executors: The Workhorses + +Executors are the processes that actually run your tasks and store data for your application. Each executor runs in its own JVM process and can run multiple tasks concurrently using threads. + +**What Executors Do:** +- Execute tasks sent from the driver +- Store computation results in memory or disk storage +- Provide in-memory storage for cached RDDs/DataFrames +- Report heartbeat and task status back to the driver + +**Key Characteristics:** +- Each executor has a fixed number of cores and amount of memory +- Executors are launched at the start of a Spark application and run for the entire lifetime +- If an executor fails, Spark can launch new ones and recompute lost data -Gather data about who will be using the product and their needs. +Think of executors as skilled workers in our restaurant analogy - they can handle multiple cooking tasks simultaneously and have their own workspace (memory) to store ingredients and intermediate results. -- ❓Who are they? -- ❓What are their goals, habits, and pain points? -- ❓What are they looking for in a product? +## How These Components Work Together: The Execution Flow -To answer these questions, you need to do some research. This involves gathering data about who will be using the product and their needs. You can find this data from surveys, focus groups, interviews, and other forms of market research. Once you have this data, you can start to design a product that meets the needs of your users. +Now that we know the players, let's see how they orchestrate a typical Spark application: -![img1](./images/spark.png) +### Step 1: Application Submission +When you submit a Spark application, the driver program starts up and contacts the cluster manager requesting resources for executors. -### 🧩 Define the Problem +### Step 2: Resource Allocation +The cluster manager examines available resources and launches executor processes on worker nodes across the cluster. -One of the most important aspects of good design is understanding the problem that needs to be solved. Too often, people focus on the solution without taking the time to understand the problem. This can lead to misguided efforts and a lot of wasted time and energy. The best way to identify the problem is to ask a lot of questions. Try to get as much information as possible from stakeholders, users, and anyone else who might have a vested interest in the project. Once you have a good understanding of the problem, you can start looking for solutions. +### Step 3: Task Planning +The driver analyzes your code and creates a logical execution plan. It breaks down operations into stages and tasks that can be executed in parallel. +### Step 4: Task Distribution +The driver sends tasks to executors. Each task operates on a partition of data, and multiple tasks can run in parallel across different executors. -### 💡 Ideate Solutions -Generate creative ideas to solve the problem. The first step in coming up with ideas is to understand the problem fully. What are its causes and effects? What are people currently doing to try to solve it? Once you have a good understanding of the problem, you can start brainstorming potential solutions. To generate creative ideas, it can be helpful to think about things from different angles. Try approaching the problem from different perspectives, using different methods or tools, or looking at it from a different time period. Sometimes all it takes is a fresh perspective to come up with a great solution. +### Step 5: Execution and Communication +Executors run the tasks, storing intermediate results and communicating progress back to the driver. The driver coordinates everything and handles any failures. -- ✅Think outside the box -- ✅Use different methods and perspectives -- ✅Brainstorm with your team or solo +### Step 6: Result Collection +Once all tasks complete, the driver collects results and returns the final output to your application. -Approach problems from multiple angles. Innovation often comes from seeing something in a new light. +## Understanding RDDs: The Foundation +At the heart of Spark's architecture lies the concept of Resilient Distributed Datasets (RDDs). Understanding RDDs is crucial to understanding how Spark actually works. -### 🛠️ Refine the Solution -Select the best idea and make it more specific. +**What makes RDDs special:** -The best way to improve a solution is to select the best idea and make it more specific. This will help to focus the team on the most important aspects of the problem. This can be done in a number of ways, but the most effective is to break the idea down into smaller chunks that can be easily addressed. Once the smaller chunks have been defined, it becomes easier to see how they fit together and whether or not they are feasible. Making a solution more specific has several benefits. It can help to focus the team on what needs to be done and make sure that everyone is on the same page. +**Resilient:** RDDs can automatically recover from node failures. Spark remembers how each RDD was created (its lineage) and can rebuild lost partitions. -- ✅Focus on high-impact features -- ✅Define clear goals -- ✅Ensure everyone is aligned +**Distributed:** RDD data is automatically partitioned and distributed across multiple nodes in the cluster. -Refining makes execution manageable and ensures the solution directly addresses the user problem.There are different types of prototypes that you can use, depending on what you want to test with users. These include low-fidelity prototypes, which are sketches or wireframes of the product; high-fidelity prototypes, which are more realistic versions of the product; and paper prototypes, which are sketches. +**Dataset:** At the end of the day, it's still just a collection of your data - but with superpowers. +### RDD Operations: Transformations vs Actions -### 🧪 Develop Prototypes -Create a basic version of the solution to test with users. Prototyping is the process of creating a basic or preliminary version of a product or service to test with users. The goal of prototyping is to get feedback from potential users early in the design process so that you can make changes and improvements before you invest too much time and money in the final product. You can use prototypes for different types of products, such as websites, apps, and software. +RDDs support two types of operations, and understanding the difference is crucial: -### Types of Prototypes: -- ✅**Low-fidelity:** Sketches, wireframes -- ✅**High-fidelity:** Interactive, realistic simulations -- ✅**Paper prototypes:** Simple, hand-drawn flows +**Transformations** (Lazy): +```scala +val filtered = data.filter(x => x > 10) +val mapped = filtered.map(x => x * 2) +val grouped = mapped.groupByKey() +``` +These operations don't actually execute immediately. Spark just builds up a computation graph. -Prototypes help gather feedback early and avoid costly mistakes later in development. +**Actions** (Eager): +```scala +val results = grouped.collect() // Brings data to driver +val count = filtered.count() // Returns number of elements +grouped.saveAsTextFile("hdfs://...") // Saves to storage +``` +Actions trigger the actual execution of all the transformations in the lineage. +This lazy evaluation allows Spark to optimize the entire computation pipeline before executing anything. +## The DAG: Spark's Optimization Engine -### 📣 Collect Feedback from Users +One of Spark's most elegant features is how it converts your operations into a Directed Acyclic Graph (DAG) for optimal execution. -Feedback is a crucial part of the design process. We need to collect feedback from users to make sure that the prototype solves their needs. This will help us design a better product. The feedback we collect can be qualitative or quantitative, but it is most often qualitative because it is easier to get responses; can be collected in many different ways, such as through surveys and interviews. -Test your prototype with real users to understand: +### How DAG Optimization Works -- ✅Does it solve their needs? -- ✅Is the experience smooth and intuitive? +When you chain multiple transformations together, Spark doesn't execute them immediately. Instead, it builds a DAG that represents the computation. This allows for powerful optimizations: -Gather both **qualitative** and **quantitative** feedback through interviews, usability testing, and surveys. Use that data to iterate and improve. 🔁 +**Pipelining:** Multiple transformations that don't require data shuffling can be combined into a single stage and executed together. +**Stage Boundaries:** Spark creates stage boundaries at operations that require data shuffling (like `groupByKey`, `join`, or `repartition`). -### 🚀 Launch the Product +### Stages and Tasks Breakdown -Launching a product is a tough task. Especially when it comes to public release. You have to make sure that you are ready for any feedback and criticism you might receive. -When launching your product, there are many factors that need to be taken into accounts such as feedback, the market, and the competition. There are many things that can go wrong when releasing your product publicly. However, with careful planning and taking all of these factors into account, a successful launch is possible. +**Stage:** A set of tasks that can all be executed without data shuffling. All tasks in a stage can run in parallel. -Incorporate feedback, finalize features, and release your product to the public. +**Task:** The smallest unit of work in Spark. Each task processes one partition of data. -- ✅Prepare for feedback and iteration -- ✅Know your market and competitors -- ✅Stay user-focused even after launch +**Wide vs Narrow Dependencies:** +- **Narrow Dependencies:** Each partition of child RDD depends on a constant number of parent partitions (like `map`, `filter`) +- **Wide Dependencies:** Each partition of child RDD may depend on multiple parent partitions (like `groupByKey`, `join`) -A successful launch comes from ongoing improvement and close attention to your users’ evolving needs. Whether you’re a sole UX designer, part of a team, or working for a large organization, these are certain steps that you need to follow in order to achieve your goals effectively. The seven steps listed above are not easy. They take time, effort, and a strong aptitude for problem-solving. Yet, Executing the above steps correctly will maximize your chances of success, while failing to address key steps along the way could sink your whole project, with the right mentors, direction, and guidance, they can help aspiring UX designers reach their goals almost as fast as they set them. +Wide dependencies create stage boundaries because they require shuffling data across the network. -### 🧘‍♀️ Takeaway: Build with Users, Not Just for Them +## Memory Management: Where the Magic Happens -Whether you're a solo UX designer or working in a large team, these 7 steps are crucial. They require time, effort, and problem-solving skills—but skipping any of them can cost you the success of your product. +Spark's memory management is what gives it the speed advantage over traditional batch processing systems. Here's how it works: -With strong mentorship and direction, aspiring UX designers can move faster and more confidently in their careers. +### Memory Regions -## ✅ Final Verdict +Spark divides executor memory into several regions: -If you’ve made it this far—thank you! 🙌 -I hope this guide helped you better understand how to **streamline your UX design process**. -If you found value in it, please share it with your fellow designers and friends. +**Storage Memory (60% by default):** +- Used for caching RDDs/DataFrames +- LRU eviction when space is needed +- Can borrow from execution memory when available + +**Execution Memory (20% by default):** +- Used for computation in shuffles, joins, sorts, aggregations +- Can borrow from storage memory when needed + +**User Memory (20% by default):** +- For user data structures and internal metadata +- Not managed by Spark + +**Reserved Memory (300MB by default):** +- System reserved memory for Spark's internal objects + +The beautiful thing about this system is that storage and execution memory can dynamically borrow from each other based on current needs. + +## The Unified Stack: Multiple APIs, One Engine + +What makes Spark truly powerful is that it provides multiple high-level APIs that all run on the same core engine: + +### Spark Core +The foundation that provides: +- Basic I/O functionality +- Task scheduling and memory management +- Fault tolerance +- RDD abstraction + +### Spark SQL +- SQL queries on structured data +- DataFrame and Dataset APIs +- Catalyst query optimizer +- Integration with various data sources + +### Spark Streaming +- Real-time stream processing +- Micro-batch processing model +- Integration with streaming sources like Kafka + +### MLlib +- Distributed machine learning algorithms +- Feature transformation utilities +- Model evaluation and tuning + +### GraphX +- Graph processing and analysis +- Built-in graph algorithms +- Graph-parallel computation + +The key insight: all of these APIs compile down to the same core RDD operations, so they all benefit from Spark's optimization engine and can interoperate seamlessly. + +## Putting It All Together + +Now that we've covered all the components, let's see how they work together in a real example: + +```scala +// This creates RDDs but doesn't execute anything yet +val textFile = spark.textFile("hdfs://large-file.txt") +val words = textFile.flatMap(line => line.split(" ")) +val wordCounts = words.map(word => (word, 1)) +val aggregated = wordCounts.reduceByKey(_ + _) + +// This action triggers execution of the entire pipeline +val results = aggregated.collect() +``` + +**What happens behind the scenes:** +1. Driver creates a DAG with two stages (split by the `reduceByKey` shuffle) +2. Driver requests executors from cluster manager +3. Stage 1 tasks (read, flatMap, map) execute on partitions across executors +4. Data gets shuffled for the `reduceByKey` operation +5. Stage 2 tasks perform the aggregation +6. Results get collected back to the driver + +## Why This Architecture Matters + +Understanding Spark's architecture isn't just academic knowledge - it's the key to working effectively with big data: + +**Fault Tolerance:** The RDD lineage graph means Spark can recompute lost data automatically without manual intervention. + +**Scalability:** The driver/executor model scales horizontally - just add more worker nodes to handle bigger datasets. + +**Efficiency:** Lazy evaluation and DAG optimization mean Spark can optimize entire computation pipelines before executing anything. + +**Flexibility:** The unified stack means you can mix SQL, streaming, and machine learning in the same application without data movement penalties. + +## Conclusion: The Beauty of Distributed Computing + +Spark's architecture represents one of the most elegant solutions to distributed computing that I've encountered. By clearly separating concerns - coordination (driver), resource management (cluster manager), and execution (executors) - Spark creates a system that's both powerful and understandable. + +The magic isn't in any single component, but in how they all work together. The driver's intelligence in creating optimal execution plans, the cluster manager's efficiency in resource allocation, and the executors' reliability in task execution combine to create something greater than the sum of its parts. + +Whether you're processing terabytes of log data, training machine learning models, or running real-time analytics, understanding this architecture will help you reason about performance, debug issues, and design better data processing solutions. + +--- -📩 Contact: **sowmiyavenkatesan611@gmail.com** f +*The next time you see a Spark architecture diagram, I hope you'll see what I see now - not a confusing web of boxes and arrows, but an elegant dance of distributed computing components working in perfect harmony. Happy Sparking! 🚀* -Happy Designing! 🎨 \ No newline at end of file diff --git a/src/components/mockup/DeveloperMockup.tsx b/src/components/mockup/DeveloperMockup.tsx new file mode 100644 index 00000000..d71b6da4 --- /dev/null +++ b/src/components/mockup/DeveloperMockup.tsx @@ -0,0 +1,209 @@ +import React, { useState } from 'react'; +import { motion } from 'framer-motion'; +import { useColorMode } from '@docusaurus/theme-common'; + +interface MockupItem { + title: string; + image: string; + description: string; +} + +interface DeveloperMockupProps { + items: MockupItem[]; +} + +const DeveloperMockup: React.FC = ({ items }) => { + const [activeIndex, setActiveIndex] = useState(0); + const { colorMode } = useColorMode(); + const isDark = colorMode === 'dark'; + + return ( +
    + {/* Section Header */} +
    + + Live Preview + + + Interactive Project Showcase + + + Explore our featured projects with live previews and detailed insights + +
    + + {/* Mockup Container */} + +
    + {/* Enhanced Sidebar */} +
    +
    +
    +

    + Featured Projects +

    +
    + +
    + {items.map((item, index) => ( + setActiveIndex(index)} + className={`relative p-5 rounded-xl cursor-pointer transition-all duration-300 overflow-hidden ${ + activeIndex === index + ? 'bg-gradient-to-r from-blue-500 to-purple-600 text-white shadow-xl transform scale-105' + : isDark + ? 'bg-gray-700/50 hover:bg-gray-600/70 text-gray-200 border border-gray-600' + : 'bg-white hover:bg-gray-50 text-gray-700 shadow-md border border-gray-200' + }`} + > + {activeIndex === index && ( + + )} + +
    +
    +

    {item.title}

    +

    + {item.description} +

    +
    +
    +
    + + {activeIndex === index && ( + + )} + + ))} +
    +
    + + {/* Enhanced Main Screen */} +
    +
    + {/* Enhanced Browser Header */} +
    +
    +
    +
    +
    +
    +
    + 🔒 + github.com/recodehive/{items[activeIndex]?.title.toLowerCase().replace(/\s+/g, '-')} +
    +
    + Live +
    +
    + + {/* Enhanced Screenshot Display */} +
    + + {items[activeIndex]?.title} + + {/* Enhanced Overlay */} +
    +
    + +
    +
    + Active Project +
    +

    {items[activeIndex]?.title}

    +

    + {items[activeIndex]?.description} +

    + + View Project → + +
    +
    +
    +
    +
    +
    +
    +
    + +
    + ); +}; + +export default DeveloperMockup; \ No newline at end of file diff --git a/src/components/ourProjects.tsx b/src/components/ourProjects.tsx index 57e51a9a..5de0f008 100644 --- a/src/components/ourProjects.tsx +++ b/src/components/ourProjects.tsx @@ -95,6 +95,15 @@ const HeadingComponent = ({ ); }; +// Helper function to get website URLs +const getWebsiteUrl = (title: string) => { + const urls = { + "Awesome GitHub Profile": "https://recodehive.github.io/awesome-github-profiles/", + "Machine Learning Repository": "https://machine-learning-repos.vercel.app/" + }; + return urls[title] || "https://github.com/recodehive"; +}; + // Select Component const SelectComponent = ({ items, @@ -149,28 +158,304 @@ const SelectComponent = ({ ))}
    - setIsHovered(true)} - onHoverEnd={() => setIsHovered(false)} - className={`col-span-1 md:col-span-8 p-0 md:p-8 ${ - isDark ? "bg-[#1a1a1a]" : "bg-white" - } transition-colors duration-300`} - > - + {/* Animated Mesh Background */} +
    +
    +
    +
    + + {/* Particle System */} +
    + {[...Array(12)].map((_, i) => ( + + ))} +
    + + {/* Advanced Floating Icons */} + + + + +
    +
    + + + + + + + 🚀 + + + {/* Holographic Main Browser */} + -
    + initial={{ opacity: 0, rotateY: -20, scale: 0.8, z: -100 }} + animate={{ opacity: 1, rotateY: 0, scale: 1, z: 0 }} + transition={{ duration: 0.8, ease: "easeOut" }} + className="relative z-10 perspective-1000" + > +
    + {/* Holographic Border Effect */} +
    + + {/* Premium Browser Header */} +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    + 🔒 + github.com + / + recodehive + / + + {items[activeItem].title.toLowerCase().replace(/\s+/g, '-')} + +
    + + + + LIVE + +
    + + {/* Ultra-Enhanced Screenshot Display */} +
    + + {(items[activeItem].title === "Awesome GitHub Profile" || items[activeItem].title === "Machine Learning Repository") ? ( + /* Auto-scrolling Website Iframe */ + window.open(getWebsiteUrl(items[activeItem].title), '_blank')} + > + + + ) : ( + /* Interactive Screenshot for other projects */ + window.open(getWebsiteUrl(items[activeItem].title), '_blank')} + > + + + {/* Click to Visit Overlay */} +
    + + 🔗 Click to Visit Repository + +
    +
    + )} + + {/* Dynamic Indicator */} + + {(items[activeItem].title === "Awesome GitHub Profile" || items[activeItem].title === "Machine Learning Repository") ? ( + <> +
    + Auto-scrolling Live Site + + ) : ( + "👆 Hover & Click to Explore" + )} +
    + + {/* Holographic Overlay */} +
    +
    +
    + + +
    +
    +
    + + + {/* 3D Floating Background Mockups */} +
    + {items.map((item, index) => { + if (index === activeItem) return null; + const positions = [ + { top: '8%', left: '2%', rotate: '-15deg', scale: '0.25', z: '-50px' }, + { top: '65%', left: '5%', rotate: '12deg', scale: '0.22', z: '-30px' }, + { top: '15%', right: '3%', rotate: '18deg', scale: '0.28', z: '-40px' }, + { bottom: '12%', right: '6%', rotate: '-10deg', scale: '0.20', z: '-60px' } + ]; + const pos = positions[index % positions.length]; + + return ( + + +
    +
    +
    +
    +
    +
    +
    +
    + {item.title} +
    +
    +
    +
    + ); + })} +
    +
    ); }; diff --git a/src/database/blogs/index.tsx b/src/database/blogs/index.tsx index 3846ea32..4483f79d 100644 --- a/src/database/blogs/index.tsx +++ b/src/database/blogs/index.tsx @@ -58,12 +58,12 @@ const blogs: Blog[] = [ slug: "git-coding-agent", }, { - id: 6, + id: 7, title: "Apache Spark Tutorial", image: "/img/blogs/07-spark-blog-banner.png", description: "Apache Spark is an open-source unified analytics engine for large-scale data processing, with built-in modules for streaming, SQL, machine learning, and graph processing.", - slug: "spark-architecture", + slug: "Spark-Architecture", }, ]; From fd25346474904807d9f704a2b6b16814021f82f2 Mon Sep 17 00:00:00 2001 From: YourGitHubUsername Date: Thu, 21 Aug 2025 18:21:05 +0530 Subject: [PATCH 4/6] updated --- blog/Spark-Architecture/index.md | 309 ----------------------- blog/spark-architecture/images/spark.png | Bin 115143 -> 0 bytes blog/spark-architecture/index.md | 309 ----------------------- src/database/blogs/index.tsx | 20 +- 4 files changed, 10 insertions(+), 628 deletions(-) delete mode 100644 blog/Spark-Architecture/index.md delete mode 100644 blog/spark-architecture/images/spark.png delete mode 100644 blog/spark-architecture/index.md diff --git a/blog/Spark-Architecture/index.md b/blog/Spark-Architecture/index.md deleted file mode 100644 index 92338b86..00000000 --- a/blog/Spark-Architecture/index.md +++ /dev/null @@ -1,309 +0,0 @@ ---- -title: "Spark Architecture Explained" -authors: [Aditya-Singh-Rathore] -tags: [Apache Spark, Spark Architecture, Big Data, Distributed Computing, Data Engineering] -date: 2025-08-18 - -description: Apache Spark is a fast, open-source big data framework that leverages in-memory computing for high performance. Its architecture powers scalable distributed processing across clusters, making it essential for analytics and machine learning. - -draft: false -canonical_url: -# meta: -# - name: "robots" -# content: "index, follow" -# - property: "og:title" -# content: "What is Google DeepMind AI?" -# - property: "og:description" -# content: "DeepMind is an auxiliary of Google that centers around man-made brainpower. All the more explicitly, it utilizes a part of AI called AI" -# - property: "og:type" -# content: "article" -# - property: "og:url" -# content: "/blog/getting-started-with-mern" -# - property: "og:image" -# content: "/assets/images/mern-8a27add30515e58f789f89a4c9072818.jpg" -# - name: "twitter:card" -# content: "summary_large_image" -# - name: "twitter:title" -# content: "A Comprehensive Guide to Get You Started with MERN Stack" -# - name: "twitter:description" -# content: "DeepMind is an auxiliary of Google that centers around man-made brainpower. All the more explicitly, it utilizes a part of AI called AI" -# - name: "twitter:image" -# content: "assets/images/mern-8a27add30515e58f789f89a4c9072818.jpg" - ---- - -# Understanding Apache Spark Architecture: A Deep Dive into Distributed Computing - -Hey there, fellow data enthusiasts! 👋 - -I remember the first time I encountered a Spark architecture diagram. It looked like a complex web of boxes and arrows that seemed to communicate in some secret distributed computing language. But once I understood what each component actually does and how they work together, everything clicked into place. - -Today, I want to walk you through Spark's architecture in a way that I wish someone had explained it to me back then - focusing on the core components and how this beautiful system actually works under the hood. - -## What is Apache Spark? - -Before diving into the architecture, let's establish what we're dealing with. Apache Spark is an open-source, distributed computing framework designed to process massive datasets across clusters of computers. Think of it as a coordinator that can take your data processing job and intelligently distribute it across multiple machines to get the work done faster. - -The key insight that makes Spark special? It keeps data in memory between operations whenever possible, which is why it can be dramatically faster than traditional batch processing systems. - -## The Big Picture: High-Level Architecture - -![Spark Architecture](/img/blogs/07-spark_architecture.png) - - -When you look at Spark's architecture, you're essentially looking at a well-orchestrated system with three main types of components working together: - -1. **Driver Program** - The mastermind that coordinates everything -2. **Cluster Manager** - The resource allocator -3. **Executors** - The workers that do the actual processing - -Let's break down each of these and understand how they collaborate. - -## Core Components Deep Dive - -### 1. The Driver Program: Your Application's Brain - -The Driver Program is where your Spark application begins and ends. When you write a Spark program and run it, you're essentially creating a driver program. Here's what makes it the brain of the operation: - -**What the Driver Does:** -- Contains your main() function and defines RDDs and operations on them -- Converts your high-level operations into a DAG (Directed Acyclic Graph) of tasks -- Schedules tasks across the cluster -- Coordinates with the cluster manager to get resources -- Collects results from executors and returns final results - -**Think of it this way:** If your Spark application were a restaurant, the Driver would be the head chef who takes orders (your code), breaks them down into specific cooking tasks, assigns those tasks to kitchen staff (executors), and ensures everything comes together for the final dish. - -The driver runs in its own JVM process and maintains all the metadata about your Spark application throughout its lifetime. - -### 2. Cluster Manager: The Resource Referee - -The Cluster Manager sits between your driver and the actual compute resources. Its job is to allocate and manage resources across the cluster. Spark is flexible and works with several cluster managers: - -**Standalone Cluster Manager:** -- Spark's built-in cluster manager -- Simple to set up and understand -- Great for dedicated Spark clusters - -**Apache YARN (Yet Another Resource Negotiator):** -- Hadoop's resource manager -- Perfect if you're in a Hadoop ecosystem -- Allows resource sharing between Spark and other Hadoop applications - -**Apache Mesos:** -- A general-purpose cluster manager -- Can handle multiple frameworks beyond just Spark -- Good for mixed workload environments - -**Kubernetes:** -- The modern container orchestration platform -- Increasingly popular for new deployments -- Excellent for cloud-native environments - -**The key point:** The cluster manager's job is resource allocation - it doesn't care what your application does, just how much CPU and memory it needs. - -### 3. Executors: The Workhorses - -Executors are the processes that actually run your tasks and store data for your application. Each executor runs in its own JVM process and can run multiple tasks concurrently using threads. - -**What Executors Do:** -- Execute tasks sent from the driver -- Store computation results in memory or disk storage -- Provide in-memory storage for cached RDDs/DataFrames -- Report heartbeat and task status back to the driver - -**Key Characteristics:** -- Each executor has a fixed number of cores and amount of memory -- Executors are launched at the start of a Spark application and run for the entire lifetime -- If an executor fails, Spark can launch new ones and recompute lost data - -Think of executors as skilled workers in our restaurant analogy - they can handle multiple cooking tasks simultaneously and have their own workspace (memory) to store ingredients and intermediate results. - -## How These Components Work Together: The Execution Flow - -Now that we know the players, let's see how they orchestrate a typical Spark application: - -### Step 1: Application Submission -When you submit a Spark application, the driver program starts up and contacts the cluster manager requesting resources for executors. - -### Step 2: Resource Allocation -The cluster manager examines available resources and launches executor processes on worker nodes across the cluster. - -### Step 3: Task Planning -The driver analyzes your code and creates a logical execution plan. It breaks down operations into stages and tasks that can be executed in parallel. - -### Step 4: Task Distribution -The driver sends tasks to executors. Each task operates on a partition of data, and multiple tasks can run in parallel across different executors. - -### Step 5: Execution and Communication -Executors run the tasks, storing intermediate results and communicating progress back to the driver. The driver coordinates everything and handles any failures. - -### Step 6: Result Collection -Once all tasks complete, the driver collects results and returns the final output to your application. - -## Understanding RDDs: The Foundation - -At the heart of Spark's architecture lies the concept of Resilient Distributed Datasets (RDDs). Understanding RDDs is crucial to understanding how Spark actually works. - -**What makes RDDs special:** - -**Resilient:** RDDs can automatically recover from node failures. Spark remembers how each RDD was created (its lineage) and can rebuild lost partitions. - -**Distributed:** RDD data is automatically partitioned and distributed across multiple nodes in the cluster. - -**Dataset:** At the end of the day, it's still just a collection of your data - but with superpowers. - -### RDD Operations: Transformations vs Actions - -RDDs support two types of operations, and understanding the difference is crucial: - -**Transformations** (Lazy): -```scala -val filtered = data.filter(x => x > 10) -val mapped = filtered.map(x => x * 2) -val grouped = mapped.groupByKey() -``` -These operations don't actually execute immediately. Spark just builds up a computation graph. - -**Actions** (Eager): -```scala -val results = grouped.collect() // Brings data to driver -val count = filtered.count() // Returns number of elements -grouped.saveAsTextFile("hdfs://...") // Saves to storage -``` -Actions trigger the actual execution of all the transformations in the lineage. - -This lazy evaluation allows Spark to optimize the entire computation pipeline before executing anything. - -## The DAG: Spark's Optimization Engine - -One of Spark's most elegant features is how it converts your operations into a Directed Acyclic Graph (DAG) for optimal execution. - -### How DAG Optimization Works - -When you chain multiple transformations together, Spark doesn't execute them immediately. Instead, it builds a DAG that represents the computation. This allows for powerful optimizations: - -**Pipelining:** Multiple transformations that don't require data shuffling can be combined into a single stage and executed together. - -**Stage Boundaries:** Spark creates stage boundaries at operations that require data shuffling (like `groupByKey`, `join`, or `repartition`). - -### Stages and Tasks Breakdown - -**Stage:** A set of tasks that can all be executed without data shuffling. All tasks in a stage can run in parallel. - -**Task:** The smallest unit of work in Spark. Each task processes one partition of data. - -**Wide vs Narrow Dependencies:** -- **Narrow Dependencies:** Each partition of child RDD depends on a constant number of parent partitions (like `map`, `filter`) -- **Wide Dependencies:** Each partition of child RDD may depend on multiple parent partitions (like `groupByKey`, `join`) - -Wide dependencies create stage boundaries because they require shuffling data across the network. - -## Memory Management: Where the Magic Happens - -Spark's memory management is what gives it the speed advantage over traditional batch processing systems. Here's how it works: - -### Memory Regions - -Spark divides executor memory into several regions: - -**Storage Memory (60% by default):** -- Used for caching RDDs/DataFrames -- LRU eviction when space is needed -- Can borrow from execution memory when available - -**Execution Memory (20% by default):** -- Used for computation in shuffles, joins, sorts, aggregations -- Can borrow from storage memory when needed - -**User Memory (20% by default):** -- For user data structures and internal metadata -- Not managed by Spark - -**Reserved Memory (300MB by default):** -- System reserved memory for Spark's internal objects - -The beautiful thing about this system is that storage and execution memory can dynamically borrow from each other based on current needs. - -## The Unified Stack: Multiple APIs, One Engine - -What makes Spark truly powerful is that it provides multiple high-level APIs that all run on the same core engine: - -### Spark Core -The foundation that provides: -- Basic I/O functionality -- Task scheduling and memory management -- Fault tolerance -- RDD abstraction - -### Spark SQL -- SQL queries on structured data -- DataFrame and Dataset APIs -- Catalyst query optimizer -- Integration with various data sources - -### Spark Streaming -- Real-time stream processing -- Micro-batch processing model -- Integration with streaming sources like Kafka - -### MLlib -- Distributed machine learning algorithms -- Feature transformation utilities -- Model evaluation and tuning - -### GraphX -- Graph processing and analysis -- Built-in graph algorithms -- Graph-parallel computation - -The key insight: all of these APIs compile down to the same core RDD operations, so they all benefit from Spark's optimization engine and can interoperate seamlessly. - -## Putting It All Together - -Now that we've covered all the components, let's see how they work together in a real example: - -```scala -// This creates RDDs but doesn't execute anything yet -val textFile = spark.textFile("hdfs://large-file.txt") -val words = textFile.flatMap(line => line.split(" ")) -val wordCounts = words.map(word => (word, 1)) -val aggregated = wordCounts.reduceByKey(_ + _) - -// This action triggers execution of the entire pipeline -val results = aggregated.collect() -``` - -**What happens behind the scenes:** -1. Driver creates a DAG with two stages (split by the `reduceByKey` shuffle) -2. Driver requests executors from cluster manager -3. Stage 1 tasks (read, flatMap, map) execute on partitions across executors -4. Data gets shuffled for the `reduceByKey` operation -5. Stage 2 tasks perform the aggregation -6. Results get collected back to the driver - -## Why This Architecture Matters - -Understanding Spark's architecture isn't just academic knowledge - it's the key to working effectively with big data: - -**Fault Tolerance:** The RDD lineage graph means Spark can recompute lost data automatically without manual intervention. - -**Scalability:** The driver/executor model scales horizontally - just add more worker nodes to handle bigger datasets. - -**Efficiency:** Lazy evaluation and DAG optimization mean Spark can optimize entire computation pipelines before executing anything. - -**Flexibility:** The unified stack means you can mix SQL, streaming, and machine learning in the same application without data movement penalties. - -## Conclusion: The Beauty of Distributed Computing - -Spark's architecture represents one of the most elegant solutions to distributed computing that I've encountered. By clearly separating concerns - coordination (driver), resource management (cluster manager), and execution (executors) - Spark creates a system that's both powerful and understandable. - -The magic isn't in any single component, but in how they all work together. The driver's intelligence in creating optimal execution plans, the cluster manager's efficiency in resource allocation, and the executors' reliability in task execution combine to create something greater than the sum of its parts. - -Whether you're processing terabytes of log data, training machine learning models, or running real-time analytics, understanding this architecture will help you reason about performance, debug issues, and design better data processing solutions. - ---- - -*The next time you see a Spark architecture diagram, I hope you'll see what I see now - not a confusing web of boxes and arrows, but an elegant dance of distributed computing components working in perfect harmony. Happy Sparking! 🚀* - - \ No newline at end of file diff --git a/blog/spark-architecture/images/spark.png b/blog/spark-architecture/images/spark.png deleted file mode 100644 index 514daaa041feec00ea3e4d4d73d9b8cd2d4e2bbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115143 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 =q955j@0(r$;C#Y+;_u+4DQ!ioGQrE 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 z
    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 OBP}j3RwAPB`~LuIF x > 10) -val mapped = filtered.map(x => x * 2) -val grouped = mapped.groupByKey() -``` -These operations don't actually execute immediately. Spark just builds up a computation graph. - -**Actions** (Eager): -```scala -val results = grouped.collect() // Brings data to driver -val count = filtered.count() // Returns number of elements -grouped.saveAsTextFile("hdfs://...") // Saves to storage -``` -Actions trigger the actual execution of all the transformations in the lineage. - -This lazy evaluation allows Spark to optimize the entire computation pipeline before executing anything. - -## The DAG: Spark's Optimization Engine - -One of Spark's most elegant features is how it converts your operations into a Directed Acyclic Graph (DAG) for optimal execution. - -### How DAG Optimization Works - -When you chain multiple transformations together, Spark doesn't execute them immediately. Instead, it builds a DAG that represents the computation. This allows for powerful optimizations: - -**Pipelining:** Multiple transformations that don't require data shuffling can be combined into a single stage and executed together. - -**Stage Boundaries:** Spark creates stage boundaries at operations that require data shuffling (like `groupByKey`, `join`, or `repartition`). - -### Stages and Tasks Breakdown - -**Stage:** A set of tasks that can all be executed without data shuffling. All tasks in a stage can run in parallel. - -**Task:** The smallest unit of work in Spark. Each task processes one partition of data. - -**Wide vs Narrow Dependencies:** -- **Narrow Dependencies:** Each partition of child RDD depends on a constant number of parent partitions (like `map`, `filter`) -- **Wide Dependencies:** Each partition of child RDD may depend on multiple parent partitions (like `groupByKey`, `join`) - -Wide dependencies create stage boundaries because they require shuffling data across the network. - -## Memory Management: Where the Magic Happens - -Spark's memory management is what gives it the speed advantage over traditional batch processing systems. Here's how it works: - -### Memory Regions - -Spark divides executor memory into several regions: - -**Storage Memory (60% by default):** -- Used for caching RDDs/DataFrames -- LRU eviction when space is needed -- Can borrow from execution memory when available - -**Execution Memory (20% by default):** -- Used for computation in shuffles, joins, sorts, aggregations -- Can borrow from storage memory when needed - -**User Memory (20% by default):** -- For user data structures and internal metadata -- Not managed by Spark - -**Reserved Memory (300MB by default):** -- System reserved memory for Spark's internal objects - -The beautiful thing about this system is that storage and execution memory can dynamically borrow from each other based on current needs. - -## The Unified Stack: Multiple APIs, One Engine - -What makes Spark truly powerful is that it provides multiple high-level APIs that all run on the same core engine: - -### Spark Core -The foundation that provides: -- Basic I/O functionality -- Task scheduling and memory management -- Fault tolerance -- RDD abstraction - -### Spark SQL -- SQL queries on structured data -- DataFrame and Dataset APIs -- Catalyst query optimizer -- Integration with various data sources - -### Spark Streaming -- Real-time stream processing -- Micro-batch processing model -- Integration with streaming sources like Kafka - -### MLlib -- Distributed machine learning algorithms -- Feature transformation utilities -- Model evaluation and tuning - -### GraphX -- Graph processing and analysis -- Built-in graph algorithms -- Graph-parallel computation - -The key insight: all of these APIs compile down to the same core RDD operations, so they all benefit from Spark's optimization engine and can interoperate seamlessly. - -## Putting It All Together - -Now that we've covered all the components, let's see how they work together in a real example: - -```scala -// This creates RDDs but doesn't execute anything yet -val textFile = spark.textFile("hdfs://large-file.txt") -val words = textFile.flatMap(line => line.split(" ")) -val wordCounts = words.map(word => (word, 1)) -val aggregated = wordCounts.reduceByKey(_ + _) - -// This action triggers execution of the entire pipeline -val results = aggregated.collect() -``` - -**What happens behind the scenes:** -1. Driver creates a DAG with two stages (split by the `reduceByKey` shuffle) -2. Driver requests executors from cluster manager -3. Stage 1 tasks (read, flatMap, map) execute on partitions across executors -4. Data gets shuffled for the `reduceByKey` operation -5. Stage 2 tasks perform the aggregation -6. Results get collected back to the driver - -## Why This Architecture Matters - -Understanding Spark's architecture isn't just academic knowledge - it's the key to working effectively with big data: - -**Fault Tolerance:** The RDD lineage graph means Spark can recompute lost data automatically without manual intervention. - -**Scalability:** The driver/executor model scales horizontally - just add more worker nodes to handle bigger datasets. - -**Efficiency:** Lazy evaluation and DAG optimization mean Spark can optimize entire computation pipelines before executing anything. - -**Flexibility:** The unified stack means you can mix SQL, streaming, and machine learning in the same application without data movement penalties. - -## Conclusion: The Beauty of Distributed Computing - -Spark's architecture represents one of the most elegant solutions to distributed computing that I've encountered. By clearly separating concerns - coordination (driver), resource management (cluster manager), and execution (executors) - Spark creates a system that's both powerful and understandable. - -The magic isn't in any single component, but in how they all work together. The driver's intelligence in creating optimal execution plans, the cluster manager's efficiency in resource allocation, and the executors' reliability in task execution combine to create something greater than the sum of its parts. - -Whether you're processing terabytes of log data, training machine learning models, or running real-time analytics, understanding this architecture will help you reason about performance, debug issues, and design better data processing solutions. - ---- - -*The next time you see a Spark architecture diagram, I hope you'll see what I see now - not a confusing web of boxes and arrows, but an elegant dance of distributed computing components working in perfect harmony. Happy Sparking! 🚀* - - \ No newline at end of file diff --git a/src/database/blogs/index.tsx b/src/database/blogs/index.tsx index 4483f79d..8c87fa07 100644 --- a/src/database/blogs/index.tsx +++ b/src/database/blogs/index.tsx @@ -4,6 +4,7 @@ interface Blog { image: string; description: string; slug: string; + authors: string[]; } const blogs: Blog[] = [ @@ -14,6 +15,7 @@ const blogs: Blog[] = [ description: "User experience design can be overwhelming because of the number of factors that influence what a product should look like and how it should function.", slug: "streamline-ux-ui", + authors: ["dharshibalasubramaniyam", "sanjay-kv"], }, { @@ -23,6 +25,7 @@ const blogs: Blog[] = [ description: " Are you passionate about design and dreaming of a career in it? Or maybe you are already in the design space and looking to pivot into UI/UX? ", slug: "ux-ui-design-job", + authors: ["dharshibalasubramaniyam", "sanjay-kv"], }, { id: 3, @@ -31,6 +34,7 @@ const blogs: Blog[] = [ description: "The impact of technology on UX design is undeniable. Automation and artificial intelligence are making it easier to identify user needs and create tailored experiences.", slug: "ux-designers-ai", + authors: ["dharshibalasubramaniyam", "sanjay-kv"], }, { id: 4, @@ -39,14 +43,16 @@ const blogs: Blog[] = [ description: "DeepMind is an auxiliary of Google that centers around man-made brainpower. It utilizes a part of AI called AI", slug: "google-deepmind", + authors: ["dharshibalasubramaniyam", "sanjay-kv"], }, { id: 5, title: "What are backlinks for SEO", image: "/img/blogs/01-seo-image.png", description: - "An SEO backlink is created when one website links to another, and they’re extremely important for SEO. ", + "An SEO backlink is created when one website links to another, and they're extremely important for SEO. ", slug: "google-backlinks", + authors: ["sanjay-kv"], }, { @@ -56,15 +62,9 @@ const blogs: Blog[] = [ description: "The GitHub Copilot Coding Agent is an asynchronous software engineering agent that assists developers by suggesting code snippets", slug: "git-coding-agent", + authors: ["sanjay-kv"], }, - { - id: 7, - title: "Apache Spark Tutorial", - image: "/img/blogs/07-spark-blog-banner.png", - description: - "Apache Spark is an open-source unified analytics engine for large-scale data processing, with built-in modules for streaming, SQL, machine learning, and graph processing.", - slug: "Spark-Architecture", - }, + ]; -export default blogs; +export default blogs; \ No newline at end of file From 7238ab281ac7ee1426103c538599d1f71c4b516e Mon Sep 17 00:00:00 2001 From: YourGitHubUsername Date: Thu, 21 Aug 2025 22:53:57 +0530 Subject: [PATCH 5/6] optimised --- src/components/ourProjects.tsx | 19 +++++++++---------- src/pages/dashboard/giveaway/index.tsx | 8 ++++---- src/pages/dashboard/index.tsx | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/components/ourProjects.tsx b/src/components/ourProjects.tsx index 5de0f008..3d6bafb6 100644 --- a/src/components/ourProjects.tsx +++ b/src/components/ourProjects.tsx @@ -95,13 +95,15 @@ const HeadingComponent = ({ ); }; +// Project URLs configuration +const PROJECT_URLS: Record = { + "Awesome GitHub Profile": "https://recodehive.github.io/awesome-github-profiles/", + "Machine Learning Repository": "https://machine-learning-repos.vercel.app/" +}; + // Helper function to get website URLs const getWebsiteUrl = (title: string) => { - const urls = { - "Awesome GitHub Profile": "https://recodehive.github.io/awesome-github-profiles/", - "Machine Learning Repository": "https://machine-learning-repos.vercel.app/" - }; - return urls[title] || "https://github.com/recodehive"; + return PROJECT_URLS[title] || "https://github.com/recodehive"; }; // Select Component @@ -312,10 +314,7 @@ const SelectComponent = ({ > ) : ( diff --git a/src/pages/dashboard/giveaway/index.tsx b/src/pages/dashboard/giveaway/index.tsx index 32252f7e..b8f85eeb 100644 --- a/src/pages/dashboard/giveaway/index.tsx +++ b/src/pages/dashboard/giveaway/index.tsx @@ -461,12 +461,12 @@ const GiveawayPage: React.FC = () => { }, []); const handleTabChange = ( - tab: "home" | "discuss" | "leaderboard" | "giveaway" + tab: "home" | "discuss" | "contributors" | "giveaway" ) => { setIsMobileSidebarOpen(false); if (tab === "discuss") { history.push("/dashboard#discuss"); - } else if (tab === "leaderboard") { + } else if (tab === "contributors") { history.push("/dashboard#contributors"); } else if (tab === "home") { history.push("/dashboard"); @@ -561,12 +561,12 @@ const GiveawayPage: React.FC = () => {
  • handleTabChange("leaderboard")} + onClick={() => handleTabChange("contributors")} > - Leaderboard + Contributors
  • diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index cc1c9470..c60fb34e 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -238,7 +238,7 @@ const DashboardContent: React.FC = () => { ]; setLeaderboardData(initialData); } - }, []); + }, [leaderboardData.length]); // Discussion handlers const handleDiscussionTabChange = (tab: DiscussionTab) => { From d010c03d172ddb5048a2e44be044da549e5eec5a Mon Sep 17 00:00:00 2001 From: YourGitHubUsername Date: Thu, 21 Aug 2025 23:50:35 +0530 Subject: [PATCH 6/6] removed leaderboard.css --- src/pages/dashboard/leaderboard-page.css | 581 ----------------------- 1 file changed, 581 deletions(-) delete mode 100644 src/pages/dashboard/leaderboard-page.css diff --git a/src/pages/dashboard/leaderboard-page.css b/src/pages/dashboard/leaderboard-page.css deleted file mode 100644 index 3d8a7ad3..00000000 --- a/src/pages/dashboard/leaderboard-page.css +++ /dev/null @@ -1,581 +0,0 @@ -/* ===== MODERN LEADERBOARD PAGE STYLING ===== */ - -.leaderboard-page { - max-width: 1200px; - margin: 0 auto; - padding: 2rem; - min-height: 100vh; -} - -.leaderboard-page-header { - text-align: center; - margin-bottom: 3rem; - padding: 3rem 2rem; - background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); - border-radius: 24px; - position: relative; - overflow: hidden; - box-shadow: 0 12px 40px rgba(102, 126, 234, 0.3); -} - -[data-theme="dark"] .leaderboard-page-header { - background: linear-gradient(135deg, #4c63d2 0%, #5a4b8c 50%, #d084e0 100%); - box-shadow: 0 12px 40px rgba(76, 99, 210, 0.4); -} - -.leaderboard-page-title { - display: flex; - align-items: center; - justify-content: center; - gap: 1rem; - font-size: 3.5rem; - font-weight: 800; - margin-bottom: 1rem; - color: #ffffff; - text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); -} - -.leaderboard-page-title .highlight { - background: linear-gradient(135deg, #ffd700, #ffed4e); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - filter: drop-shadow(0 2px 4px rgba(255, 215, 0, 0.3)); -} - -.leaderboard-page-subtitle { - color: rgba(255, 255, 255, 0.95); - font-size: 1.2rem; - margin-bottom: 2rem; - text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); -} - -.filter-section { - display: flex; - justify-content: center; - margin-bottom: 2rem; -} - -.filter-buttons { - display: flex; - gap: 0.5rem; - background: var(--ifm-card-background-color); - padding: 0.5rem; - border-radius: 20px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); - border: 1px solid var(--ifm-color-emphasis-200); -} - -[data-theme="dark"] .filter-buttons { - background: var(--ifm-background-surface-color); - border: 1px solid var(--ifm-color-emphasis-300); -} - -.filter-btn { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.75rem 1.5rem; - border: none; - border-radius: 15px; - background: transparent; - color: var(--ifm-color-emphasis-700); - font-weight: 600; - cursor: pointer; - transition: all 0.3s ease; - font-size: 0.9rem; -} - -.filter-btn:hover { - background: var(--ifm-color-emphasis-100); - color: var(--ifm-color-emphasis-900); -} - -.filter-btn.active { - background: linear-gradient(135deg, var(--ifm-color-primary), var(--ifm-color-primary-dark)); - color: white; - box-shadow: 0 4px 15px rgba(var(--ifm-color-primary-rgb), 0.3); -} - -.filter-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.stats-summary { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 1.5rem; - margin-bottom: 3rem; -} - -.stat-card { - display: flex; - align-items: center; - gap: 1rem; - padding: 1.5rem; - background: var(--ifm-card-background-color); - border-radius: 20px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); - border: 1px solid var(--ifm-color-emphasis-200); - transition: all 0.3s ease; -} - -[data-theme="dark"] .stat-card { - background: var(--ifm-background-surface-color); - border: 1px solid var(--ifm-color-emphasis-300); -} - -.stat-card:hover { - transform: translateY(-2px); - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); -} - -.stat-icon { - display: flex; - align-items: center; - justify-content: center; - width: 50px; - height: 50px; - border-radius: 15px; - background: linear-gradient(135deg, var(--ifm-color-primary), var(--ifm-color-primary-dark)); - color: white; -} - -.stat-info { - flex: 1; -} - -.stat-value { - font-size: 2rem; - font-weight: 800; - color: var(--ifm-color-emphasis-900); - line-height: 1; -} - -.stat-label { - font-size: 0.9rem; - color: var(--ifm-color-emphasis-600); - margin-top: 0.25rem; -} - -.leaderboard-table-wrapper { - background: var(--ifm-card-background-color); - border-radius: 24px; - overflow: hidden; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); - border: 1px solid var(--ifm-color-emphasis-200); -} - -[data-theme="dark"] .leaderboard-table-wrapper { - background: var(--ifm-background-surface-color); - border: 1px solid var(--ifm-color-emphasis-300); -} - -.leaderboard-table { - width: 100%; -} - -.leaderboard-table-header { - display: grid; - grid-template-columns: 100px 1fr 140px 120px; - background: var(--ifm-color-emphasis-100); - padding: 1.25rem 1.5rem; - font-weight: 700; - font-size: 0.85rem; - text-transform: uppercase; - letter-spacing: 0.8px; - color: var(--ifm-color-emphasis-800); - border-bottom: 2px solid var(--ifm-color-emphasis-200); -} - -[data-theme="dark"] .leaderboard-table-header { - background: var(--ifm-color-emphasis-200); - color: var(--ifm-color-emphasis-600); -} - -.leaderboard-header-cell { - display: flex; - align-items: center; - justify-content: center; -} - -.leaderboard-header-cell.username-header { - justify-content: flex-start; -} - -.leaderboard-table-body { - display: flex; - flex-direction: column; -} - -.leaderboard-row { - display: grid; - grid-template-columns: 100px 1fr 140px 120px; - padding: 1.75rem 1.5rem; - border-bottom: 1px solid var(--ifm-color-emphasis-200); - transition: all 0.3s ease; - position: relative; -} - -[data-theme="dark"] .leaderboard-row { - border-bottom: 1px solid var(--ifm-color-emphasis-300); -} - -.leaderboard-row:hover { - background: var(--ifm-color-emphasis-100); - transform: translateX(3px); -} - -[data-theme="dark"] .leaderboard-row:hover { - background: var(--ifm-color-emphasis-200); -} - -.leaderboard-row:last-child { - border-bottom: none; -} - -.leaderboard-row.top-1 { - background: linear-gradient(135deg, rgba(255, 215, 0, 0.12) 0%, rgba(255, 193, 7, 0.04) 100%); - border-left: 4px solid #ffd700; -} - -.leaderboard-row.top-2 { - background: linear-gradient(135deg, rgba(192, 192, 192, 0.12) 0%, rgba(169, 169, 169, 0.04) 100%); - border-left: 4px solid #c0c0c0; -} - -.leaderboard-row.top-3 { - background: linear-gradient(135deg, rgba(205, 127, 50, 0.12) 0%, rgba(184, 134, 11, 0.04) 100%); - border-left: 4px solid #cd7f32; -} - -.leaderboard-cell { - display: flex; - align-items: center; - justify-content: center; -} - -.leaderboard-rank-cell { - justify-content: center; -} - -.leaderboard-rank-badge { - display: flex; - align-items: center; - justify-content: center; - width: 50px; - height: 50px; - border-radius: 50%; - font-weight: 700; - background: var(--ifm-color-emphasis-200); - color: var(--ifm-color-emphasis-800); - transition: all 0.3s ease; -} - -.leaderboard-rank-badge.rank-1 { - background: linear-gradient(135deg, #ffd700, #ffed4e); - color: #1a1a1a; - box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4); - transform: scale(1.1); -} - -.leaderboard-rank-badge.rank-2 { - background: linear-gradient(135deg, #c0c0c0, #e8e8e8); - color: #1a1a1a; - box-shadow: 0 6px 20px rgba(192, 192, 192, 0.4); - transform: scale(1.05); -} - -.leaderboard-rank-badge.rank-3 { - background: linear-gradient(135deg, #cd7f32, #daa520); - color: #ffffff; - box-shadow: 0 6px 20px rgba(205, 127, 50, 0.4); -} - -.leaderboard-user-cell { - justify-content: flex-start; -} - -.leaderboard-user-info { - display: flex; - align-items: center; - gap: 1rem; -} - -.leaderboard-user-avatar { - width: 48px; - height: 48px; - border-radius: 50%; - border: 3px solid var(--ifm-color-primary-light); - object-fit: cover; - transition: all 0.3s ease; -} - -.leaderboard-user-avatar:hover { - transform: scale(1.1); - border-color: var(--ifm-color-primary); -} - -.leaderboard-user-details { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.leaderboard-username { - font-weight: 600; - color: var(--ifm-color-emphasis-900); - font-size: 1rem; -} - -.leaderboard-user-achievements { - display: flex; - flex-wrap: wrap; - gap: 0.25rem; -} - -.leaderboard-achievement-badge { - background: var(--ifm-color-primary); - color: white; - padding: 0.2rem 0.6rem; - border-radius: 12px; - font-size: 0.65rem; - font-weight: 600; -} - -.leaderboard-points-cell { - flex-direction: column; - gap: 0.25rem; -} - -.leaderboard-points-value { - font-size: 1.75rem; - font-weight: 800; - color: var(--ifm-color-primary); -} - -.leaderboard-points-label { - font-size: 0.8rem; - color: var(--ifm-color-emphasis-600); -} - -.streak-indicator { - display: flex; - align-items: center; - gap: 0.25rem; - font-size: 0.7rem; - color: var(--ifm-color-warning); - margin-top: 0.25rem; -} - -.leaderboard-date-cell { - justify-content: center; -} - -.leaderboard-date-value { - font-size: 0.9rem; - color: var(--ifm-color-emphasis-700); - font-weight: 500; -} - -.leaderboard-cta { - margin-top: 4rem; - text-align: center; - padding: 3rem 2rem; - background: linear-gradient(135deg, var(--ifm-color-primary) 0%, var(--ifm-color-primary-dark) 100%); - border-radius: 24px; - color: white; -} - -.cta-content h3 { - font-size: 2rem; - font-weight: 700; - margin-bottom: 1rem; - color: white; -} - -.cta-content p { - font-size: 1.1rem; - margin-bottom: 2rem; - opacity: 0.9; - max-width: 600px; - margin-left: auto; - margin-right: auto; -} - -.cta-buttons { - display: flex; - gap: 1rem; - justify-content: center; - flex-wrap: wrap; -} - -.cta-primary, -.cta-secondary { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.875rem 1.75rem; - border-radius: 25px; - font-weight: 600; - text-decoration: none; - transition: all 0.3s ease; -} - -.cta-primary { - background: rgba(255, 255, 255, 0.2); - color: white; - border: 2px solid rgba(255, 255, 255, 0.3); -} - -.cta-primary:hover { - background: rgba(255, 255, 255, 0.3); - transform: translateY(-2px); - color: white; - text-decoration: none; -} - -.cta-secondary { - background: transparent; - color: white; - border: 2px solid rgba(255, 255, 255, 0.5); -} - -.cta-secondary:hover { - background: rgba(255, 255, 255, 0.1); - transform: translateY(-2px); - color: white; - text-decoration: none; -} - -.error-message { - background: linear-gradient(135deg, #fee2e2, #fecaca); - border: 1px solid #fca5a5; - border-radius: 16px; - padding: 1.5rem; - margin-bottom: 2rem; - text-align: center; -} - -[data-theme="dark"] .error-message { - background: linear-gradient(135deg, #7f1d1d, #991b1b); - border: 1px solid #dc2626; - color: #fecaca; -} - -.error-content h3 { - color: #dc2626; - margin-bottom: 0.5rem; -} - -[data-theme="dark"] .error-content h3 { - color: #fca5a5; -} - -.error-note { - font-size: 0.9rem; - opacity: 0.8; - margin-top: 0.5rem; -} - -.leaderboard-loading { - text-align: center; - padding: 4rem 2rem; - background: var(--ifm-card-background-color); - border-radius: 24px; - border: 1px solid var(--ifm-color-emphasis-200); -} - -[data-theme="dark"] .leaderboard-loading { - background: var(--ifm-background-surface-color); - border: 1px solid var(--ifm-color-emphasis-300); -} - -.leaderboard-loading-spinner { - width: 48px; - height: 48px; - border: 4px solid var(--ifm-color-emphasis-300); - border-top: 4px solid var(--ifm-color-primary); - border-radius: 50%; - animation: spin 1s linear infinite; - margin: 0 auto 1rem; -} - -@keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - -/* Responsive Design */ -@media (max-width: 768px) { - .leaderboard-page { - padding: 1rem; - } - - .leaderboard-page-title { - font-size: 2.5rem; - flex-direction: column; - gap: 0.5rem; - } - - .stats-summary { - grid-template-columns: 1fr; - gap: 1rem; - } - - .leaderboard-table-header, - .leaderboard-row { - grid-template-columns: 60px 1fr 80px; - padding: 1rem 0.75rem; - } - - .leaderboard-date-cell, - .leaderboard-header-cell:last-child { - display: none; - } - - .leaderboard-user-info { - gap: 0.75rem; - } - - .leaderboard-user-avatar { - width: 40px; - height: 40px; - } - - .leaderboard-points-value { - font-size: 1.5rem; - } -} - -@media (max-width: 480px) { - .leaderboard-page-header { - padding: 2rem 1rem; - } - - .leaderboard-page-title { - font-size: 2rem; - } - - .filter-buttons { - flex-direction: column; - width: 100%; - } - - .filter-btn { - justify-content: center; - } - - .cta-buttons { - flex-direction: column; - align-items: center; - } - - .cta-primary, - .cta-secondary { - width: 100%; - max-width: 300px; - justify-content: center; - } -} \ No newline at end of file