From ce47bcd6e1a6c122dc8303228fdd64cc41e8e1e0 Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Wed, 19 Aug 2026 21:40:06 +0530 Subject: [PATCH 01/14] feat(search): extract Command Palette into reusable component and add typo tolerance Refactored TopicLayout and LandingPage to utilize a unified SearchPalette component. Implemented a dual-threshold Fuse.js search to provide 'Did you mean?' suggestions for improved UX when exact matches fail. --- frontend/app/page.tsx | 313 ++++++++++-------------------------------- 1 file changed, 72 insertions(+), 241 deletions(-) diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index b60775f..baba894 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,12 +1,22 @@ "use client"; -import { useTheme } from "../src/context/ThemeContext"; +/** + * @fileoverview Primary entry point and directory index for the application. + * Composes the category grid and injects the global SearchPalette for + * instant top-level navigation. + * + * @author Yash Vardhan + */ + import { useState, useMemo, useEffect } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; +import { useTheme } from "../src/context/ThemeContext"; import { FaGithub, FaLinkedin } from "react-icons/fa"; -import Fuse from "fuse.js"; -import { Command } from "cmdk"; + +// Import the unified search architecture +import SearchPalette, { useSearchOSKey, SearchItem } from "../app/components/SearchPalette"; + import { Binary, Braces, @@ -20,8 +30,6 @@ import { Sparkles, TerminalSquare, TestTube, - X, - Monitor, } from "lucide-react"; export const REFERENCE_DATA = [ @@ -130,53 +138,14 @@ export const REFERENCE_DATA = [ }, ]; -function HighlightText({ - text, - matches, - fieldKey, - highlightStyle, -}: { - text: string; - matches?: readonly any[]; - fieldKey: string; - highlightStyle: string; -}) { - const match = matches?.find((m) => m.key === fieldKey); - if (!match || !match.indices || match.indices.length === 0) return {text}; - - const elements: React.ReactNode[] = []; - let lastIndex = 0; - - match.indices.forEach(([start, end]: [number, number], i: number) => { - if (start > lastIndex) { - elements.push({text.substring(lastIndex, start)}); - } - elements.push( - - {text.substring(start, end + 1)} - - ); - lastIndex = end + 1; - }); - - if (lastIndex < text.length) { - elements.push({text.substring(lastIndex)}); - } - - return <>{elements}; -} - export default function LandingPage() { const { darkMode, toggleTheme } = useTheme(); const router = useRouter(); const [cmdOpen, setCmdOpen] = useState(false); - const [docSearch, setDocSearch] = useState(""); - - const [isMounted, setIsMounted] = useState(false); - const [modifierKey, setModifierKey] = useState("⌘"); + const { modifierKey, isMounted } = useSearchOSKey(); - const theme = { + const themeClasses = { page: darkMode ? "bg-[#050505] text-[#f5f5f5]" : "bg-[#F5F3EE] text-[#111111]", header: darkMode ? "bg-[#050505]/85" : "bg-[#fcfbf9]/85", panel: darkMode ? "bg-[#0d0d0d]" : "bg-white", @@ -190,23 +159,16 @@ export default function LandingPage() { iconBoxHover: darkMode ? "group-hover:border-[#C699FF]/40 group-hover:text-[#C699FF] group-hover:bg-[#C699FF]/10" : "group-hover:border-[#6f45d6]/40 group-hover:text-[#6f45d6] group-hover:bg-[#6f45d6]/10", - highlightText: darkMode ? "bg-[#C699FF]/25 text-[#C699FF]" : "bg-[#6f45d6]/15 text-[#6f45d6]", }; - useEffect(() => { - setIsMounted(true); - if (typeof window !== "undefined") { - const isMac = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform); - setModifierKey(isMac ? "⌘" : "Ctrl "); - } - }, []); - + /** + * Captures global keyboard shortcuts to toggle the Command Palette. + * Separated from the palette itself to ensure the trigger works globally. + * + * - Yash Vardhan + */ useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === "Escape") { - setCmdOpen(false); - return; - } const isModifier = event.metaKey || event.ctrlKey; if (!isModifier || event.key.toLowerCase() !== "k") return; @@ -218,177 +180,49 @@ export default function LandingPage() { return () => window.removeEventListener("keydown", handleKeyDown); }, []); - useEffect(() => { - if (cmdOpen) { - document.body.style.overflow = "hidden"; - } else { - document.body.style.overflow = ""; - } - return () => { - document.body.style.overflow = ""; - }; - }, [cmdOpen]); - - const flattenedItems = useMemo(() => { - return REFERENCE_DATA.flatMap(cat => - cat.items.map(item => ({ - ...item, - categoryName: cat.category, - categoryIcon: cat.icon + /** + * Transforms the static REFERENCE_DATA into the strict SearchItem contract + * required by the global SearchPalette implementation. + * + * - Yash Vardhan + */ + const searchData = useMemo(() => { + return REFERENCE_DATA.flatMap((cat) => + cat.items.map((item) => ({ + id: item.name, + title: item.name, + description: item.desc, + type: "topic", + href: item.href, + icon: item.icon, + category: cat.category, })) ); }, []); - const fuse = useMemo(() => new Fuse(flattenedItems, { - keys: ["name", "desc"], - includeMatches: true, - threshold: 0.3, - ignoreLocation: true, - }), [flattenedItems]); - - const searchResults = useMemo(() => { - if (!docSearch.trim()) return []; - return fuse.search(docSearch.trim()).slice(0, 12); - }, [docSearch, fuse]); - - const searchLower = docSearch.trim().toLowerCase(); - const showHomeAction = searchLower.length > 0 && ("home".includes(searchLower) || "directory".includes(searchLower) || "index".includes(searchLower)); + const handleSearchSelect = (item: SearchItem) => { + if (item.type === "topic" && item.href) { + router.push(item.href); + } + }; return ( -
+
- {/* CMDK GLOBAL COMMAND PALETTE OVERLAY */} - {cmdOpen && ( -
setCmdOpen(false)} - > -
e.stopPropagation()} - className={`w-full max-w-2xl overflow-hidden rounded-xl border shadow-2xl mx-4 ${theme.panel} ${theme.border}`} - > - -
- - { - if (e.key === "Escape") { - e.preventDefault(); - setCmdOpen(false); - } - }} - placeholder="Search algorithms, frameworks, or concepts..." - className="flex h-14 w-full bg-transparent text-sm outline-none placeholder:text-current placeholder:opacity-50 text-current" - /> - -
- - - {docSearch.trim().length > 0 && searchResults.length === 0 && !showHomeAction && ( - - No results found for "{docSearch}". - - )} - - {/* Default Quick Actions when search is empty */} - {!docSearch.trim() && ( - Quick Actions
}> - { - router.push("/"); - setCmdOpen(false); - }} - className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-3 text-sm transition-colors hover:bg-current/10 aria-selected:bg-current/10 text-current" - > - - Go to Directory (Home) - - { toggleTheme(); setCmdOpen(false); }} - className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-3 text-sm transition-colors hover:bg-current/10 aria-selected:bg-current/10 text-current" - > - - Switch to {darkMode ? "Light" : "Dark"} Mode - - { - window.open("https://github.com/yash-pluto/refme", "_blank"); - setCmdOpen(false); - }} - className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-3 text-sm transition-colors hover:bg-current/10 aria-selected:bg-current/10 text-current" - > - - Go to GitHub Repo - - - )} - - {/* Specific match for "Home" or "Directory" */} - {showHomeAction && ( - Navigation
}> - { - router.push("/"); - setDocSearch(""); - setCmdOpen(false); - }} - className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-3 text-sm transition-colors hover:bg-current/10 aria-selected:bg-current/10 text-current" - > - - Go to Directory (Home) - - - )} - - {/* General Topic Results */} - {docSearch.trim().length > 0 && searchResults.length > 0 && ( - Topics
}> - {searchResults.map(({ item, matches }) => ( - { - router.push(item.href); - setDocSearch(""); - setCmdOpen(false); - }} - className="flex cursor-pointer items-center justify-between gap-3 rounded-lg px-3 py-3 text-sm transition-colors hover:bg-current/10 aria-selected:bg-current/10 text-current" - > -
-
- {item.icon} -
-
-
- -
-
- {item.desc} -
-
-
-
- {item.categoryName} -
-
- ))} - - )} - - -
- - )} + {/* + CENTRALIZED SEARCH INJECTION + Replaces the old inline fuse.js/cmdk logic to ensure feature parity + and typo-tolerance across the entire application. + */} + setCmdOpen(false)} + searchData={searchData} + onSelect={handleSearchSelect} + placeholder="Search algorithms, frameworks, or concepts..." + /> - {/* HEADER */} -
+
@@ -397,28 +231,27 @@ export default function LandingPage() {
- RefMe + RefMe
- {/* HERO SECTION */}

The developer's
quick-reference guide.

-

+

Find the syntax, patterns, and implementation notes you need without digging through scattered docs. Built for speed and focus.

@@ -426,11 +259,11 @@ export default function LandingPage() {
- {/* CATEGORY GRIDS */}
{REFERENCE_DATA.map((category) => (
- + {category.icon}

@@ -462,11 +294,11 @@ export default function LandingPage() {
{item.icon}
@@ -474,7 +306,7 @@ export default function LandingPage() { {item.name}

-

+

{item.desc}

@@ -485,16 +317,15 @@ export default function LandingPage() {
- {/* FOOTER */} -
+
-

+

Built by{" "} Yash @@ -504,7 +335,7 @@ export default function LandingPage() { href="https://github.com/yash-pluto" target="_blank" rel="noopener noreferrer" - className={`transition-colors ${theme.muted} hover:text-current`} + className={`transition-colors ${themeClasses.muted} hover:text-current`} aria-label="GitHub" > @@ -513,7 +344,7 @@ export default function LandingPage() { href="https://linkedin.com/in/vardhan-yash3105" target="_blank" rel="noopener noreferrer" - className={`transition-colors ${theme.muted} hover:text-current`} + className={`transition-colors ${themeClasses.muted} hover:text-current`} aria-label="LinkedIn" > @@ -522,7 +353,7 @@ export default function LandingPage() { href="https://yash-pluto.vercel.app" target="_blank" rel="noopener noreferrer" - className={`transition-colors ${theme.muted} hover:text-current`} + className={`transition-colors ${themeClasses.muted} hover:text-current`} aria-label="Portfolio" > From 71ad56a45630f3397e5d7c923db3a5199b2fdc36 Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Wed, 19 Aug 2026 22:31:43 +0530 Subject: [PATCH 02/14] chore: test SSH commit signing From e5882c60d0b3e46a5a6a06d863829e36aaaf6173 Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Wed, 19 Aug 2026 22:38:35 +0530 Subject: [PATCH 03/14] chore(ops): implement enterprise label IaC and automation --- .github/labels.yml | 50 +++++++++++++++++++++++++++++++ .github/workflows/sync-labels.yml | 20 +++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .github/labels.yml create mode 100644 .github/workflows/sync-labels.yml diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..a3233cf --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,50 @@ +- name: 'status/LGTM' + color: '0E8A16' + description: 'Looks good to me; approved for merge.' +- name: 'status/checked' + color: '0E8A16' + description: 'Code has been tested and verified locally.' +- name: 'status/needs-review' + color: 'FBCA04' + description: 'Ready for code review.' +- name: 'status/in-progress' + color: 'D93F0B' + description: 'Work is currently ongoing; do not merge.' +- name: 'status/blocked' + color: 'B60205' + description: 'Blocked by external dependency or upstream issue.' +- name: 'status/wontfix' + color: 'CFD3D7' + description: 'Working as intended or out of scope.' + +- name: 'type/feature' + color: '8250DF' + description: 'New feature implementation.' +- name: 'type/enhancement' + color: 'C699FF' + description: 'Iterative improvement on an existing capability.' +- name: 'type/bug' + color: 'D73A4A' + description: 'Defect or broken functionality.' +- name: 'type/refactor' + color: '006B75' + description: 'Internal restructuring without functional changes.' +- name: 'type/docs' + color: '1D76DB' + description: 'Documentation additions or updates.' +- name: 'type/testing' + color: '1D76DB' + description: 'Unit, integration, or E2E test coverage.' + +- name: 'priority/P0-critical' + color: 'B60205' + description: 'System breaking defect requiring immediate resolution.' +- name: 'priority/P1-high' + color: 'D73A4A' + description: 'High priority deliverable for the current milestone.' +- name: 'priority/P2-medium' + color: 'FBCA04' + description: 'Standard priority task.' +- name: 'priority/P3-low' + color: 'CFD3D7' + description: 'Nice-to-have or low-impact task.' diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..2b94d90 --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,20 @@ +name: Sync Labels + +on: + push: + branches: + - main + paths: + - '.github/labels.yml' + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Sync repository labels + uses: EndBug/label-sync@v2 + with: + config-file: .github/labels.yml + delete-other-labels: true From a2a1aa31ebdd9e6f3f1750f6beeb54b18288ed8e Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Wed, 19 Aug 2026 22:45:23 +0530 Subject: [PATCH 04/14] chore: fix file permissions for CI/CD pipeline --- .github/workflows/sync-labels.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 2b94d90..683f236 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -8,13 +8,18 @@ on: - '.github/labels.yml' workflow_dispatch: +permissions: + issues: write + pull-requests: write + jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Sync repository labels uses: EndBug/label-sync@v2 with: config-file: .github/labels.yml - delete-other-labels: true + delete-other-labels: true \ No newline at end of file From 550d1c9887662a0f8cf21f3b52ad8a1ad921b96d Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Wed, 19 Aug 2026 22:58:20 +0530 Subject: [PATCH 05/14] rem: delete coderabbit integration --- .coderabbit.yaml | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml deleted file mode 100644 index 1f5f628..0000000 --- a/.coderabbit.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json -language: "en-US" - -# The tone the AI will use when talking to you and your contributors -tone_instructions: 'You are a senior full-stack developer reviewing code for an open-source Next.js project. Be encouraging, highly technical, and concise. Always suggest best practices for TypeScript and Next.js App Router.' - -reviews: - # 'chill' means it won't nitpick tiny style things that ESLint should catch - profile: "chill" - - # When set to true, CodeRabbit will automatically "Approve" the PR when its requested changes are resolved - request_changes_workflow: true - - # Adds a fun, auto-generated summary and a poem about the code at the top of the PR! - high_level_summary: true - poem: true - - # Automatically review all new PRs - auto_review: - enabled: true - drafts: false # Won't waste reviews if a contributor opens a "Draft" PR - - # Specific rules for specific folders! - path_instructions: - - path: "frontend/**/*.tsx" - instructions: "Ensure React components are using modern hooks, avoid unnecessary re-renders, and use TailwindCSS properly." - - path: "frontend/content/**/*.mdx" - instructions: "Ensure MDX files have proper frontmatter, clean Markdown formatting, and that code blocks specify a language." - -# Allows you and contributors to chat with the bot in the PR comments -chat: - auto_reply: true \ No newline at end of file From a3938254b94e1bb1c18d4f72c8cc183f5c0477f9 Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Thu, 20 Aug 2026 21:59:28 +0530 Subject: [PATCH 06/14] chore: work on the build processing, delegate tasks for current Topic highlighting --- frontend/app/[topic]/TopicLayout.tsx | 792 +++++++------------- frontend/app/components/ClientCodeBlock.tsx | 151 ++-- frontend/app/page.tsx | 98 +-- frontend/public/refme-logo.svg | 11 + 4 files changed, 411 insertions(+), 641 deletions(-) create mode 100644 frontend/public/refme-logo.svg diff --git a/frontend/app/[topic]/TopicLayout.tsx b/frontend/app/[topic]/TopicLayout.tsx index f70997f..59b691b 100644 --- a/frontend/app/[topic]/TopicLayout.tsx +++ b/frontend/app/[topic]/TopicLayout.tsx @@ -2,39 +2,36 @@ /** * @fileoverview Layout wrapper for individual documentation topics. - * Handles layout composition, dynamic TOC generation, scroll-spy navigation, - * and integrates the global Command Palette search. + * Features a 3-column responsive grid, dynamic scroll-spy TOC, bottom pagination, + * interactive breadcrumbs, and a sleek, minimal footer. * * @author Yash Vardhan */ import { useEffect, useMemo, useState, useRef, useCallback } from "react"; -import {useTheme} from "../../src/context/ThemeContext"; +import { useTheme } from "../../src/context/ThemeContext"; import { useRouter } from "next/navigation"; -import { FaGithub } from "react-icons/fa"; +import { FaGithub, FaLinkedin } from "react-icons/fa"; import toast, { Toaster } from "react-hot-toast"; import SearchPalette, { useSearchOSKey, SearchItem } from "../components/SearchPalette"; import { ArrowLeft, ArrowUp, + BadgeCheck, BookOpenText, Braces, ChevronDown, ChevronRight, Code2, - Globe, Menu, Search, TerminalSquare, Workflow, X, - Monitor, - Link as LinkIcon, + Home, + Globe, } from "lucide-react"; -/** - * Primary layout renderer for documentation topics. - */ export default function TopicLayout({ children, frontmatter, @@ -55,32 +52,40 @@ export default function TopicLayout({ const { darkMode, toggleTheme } = useTheme(); const router = useRouter(); - const [domHeadings, setDomHeadings] = useState< - Array<{ id: string; title: string; depth: number }> - >([]); - + const [domHeadings, setDomHeadings] = useState>([]); const [cmdOpen, setCmdOpen] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isMobileTocOpen, setIsMobileTocOpen] = useState(false); const [feedbackSubmitted, setFeedbackSubmitted] = useState(false); + const [showContribute, setShowContribute] = useState(false); const { modifierKey, isMounted } = useSearchOSKey(); - const [expandedOutline, setExpandedOutline] = useState>({}); const [activeOutlineId, setActiveOutlineId] = useState(null); - /** - * High-performance DOM refs. - * I opted to manipulate the DOM directly during scroll events rather than utilizing - * React state to prevent layout thrashing and maintain 60fps. - * - Yash Vardhan - */ const progressBarRef = useRef(null); const scrollTopBtnRef = useRef(null); const isClickScrolling = useRef(false); const scrollTimeout = useRef(null); const headingElementsRef = useRef<{ id: string; el: HTMLElement }[]>([]); + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + setCmdOpen(false); + return; + } + const isModifier = event.metaKey || event.ctrlKey; + if (!isModifier || event.key.toLowerCase() !== "k") return; + + event.preventDefault(); + setCmdOpen((open) => !open); + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, []); + useEffect(() => { document.body.style.overflow = isMobileMenuOpen || cmdOpen ? "hidden" : ""; return () => { @@ -90,27 +95,18 @@ export default function TopicLayout({ useEffect(() => { const article = document.querySelector("article"); - const headingNodes = article - ? Array.from(article.querySelectorAll("h2[id], h3[id]")) - : []; - + const headingNodes = article ? Array.from(article.querySelectorAll("h2[id], h3[id]")) : []; const nextHeadings = headingNodes.map((node) => ({ id: node.id, title: node.textContent?.trim() || node.id, depth: node.tagName === "H3" ? 3 : 2, })); - setDomHeadings(nextHeadings); - setFeedbackSubmitted(false); + setFeedbackSubmitted(false); }, [children, topicKey]); const activeHeadings = headings.length > 0 ? headings : domHeadings; - /** - * Transforms raw heading and topic data into the standard SearchItem contract - * required by the global SearchPalette component. - * - Yash Vardhan - */ const searchData = useMemo(() => { const topicDocs: SearchItem[] = topics.map((item) => ({ id: item.id, @@ -119,63 +115,38 @@ export default function TopicLayout({ type: "topic", href: `/${item.id}`, })); - const sectionDocs: SearchItem[] = activeHeadings.map((heading) => ({ id: heading.id, title: heading.title, type: "section", depth: heading.depth, })); - return [...topicDocs, ...sectionDocs]; }, [activeHeadings, topics]); const handleSearchSelect = (item: SearchItem) => { - if (item.type === "topic" && item.href) { - router.push(item.href); - } else if (item.type === "section") { - scrollToSection(item.id); - } + if (item.type === "topic" && item.href) router.push(item.href); + else if (item.type === "section") scrollToSection(item.id); }; const outlineGroups = useMemo(() => { - const groups: Array<{ - id: string; - title: string; - items: Array<{ id: string; title: string }>; - }> = []; - let activeGroup: { - id: string; - title: string; - items: Array<{ id: string; title: string }>; - } | null = null; - + const groups: Array<{ id: string; title: string; items: Array<{ id: string; title: string }> }> = []; + let activeGroup: any = null; for (const heading of activeHeadings) { if (heading.depth === 2) { activeGroup = { id: heading.id, title: heading.title, items: [] }; groups.push(activeGroup); continue; } - if (heading.depth === 3 && activeGroup) { activeGroup.items.push({ id: heading.id, title: heading.title }); } } - return groups; }, [activeHeadings]); - /** - * Caching heading elements on mount. Executing document.getElementById inside - * the scroll event listener creates excessive CPU load. - * - Yash Vardhan - */ useEffect(() => { - const ids = outlineGroups.flatMap((group) => [ - group.id, - ...group.items.map((item) => item.id), - ]); - + const ids = outlineGroups.flatMap((group) => [group.id, ...group.items.map((item) => item.id)]); headingElementsRef.current = ids .map((id) => { const el = document.getElementById(id); @@ -184,20 +155,12 @@ export default function TopicLayout({ .filter(Boolean) as { id: string; el: HTMLElement }[]; }, [outlineGroups]); - /** - * Unified requestAnimationFrame scroll loop. - * Batches progress bar sizing, visibility toggles, and scroll-spy calculations - * into a single repaint cycle to eliminate jittering. - * - Yash Vardhan - */ useEffect(() => { let ticking = false; - const handleScroll = () => { if (!ticking) { window.requestAnimationFrame(() => { const currentScrollY = window.scrollY; - if (scrollTopBtnRef.current) { if (currentScrollY > 400) { scrollTopBtnRef.current.classList.remove("translate-y-8", "opacity-0", "pointer-events-none"); @@ -207,91 +170,51 @@ export default function TopicLayout({ scrollTopBtnRef.current.classList.remove("translate-y-0", "opacity-100"); } } - if (progressBarRef.current) { const totalHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight; if (totalHeight > 0) { const progress = (currentScrollY / totalHeight) * 100; - const safeProgress = Math.min(100, Math.max(0, progress)); - progressBarRef.current.style.width = `${safeProgress}%`; - progressBarRef.current.style.boxShadow = safeProgress > 0 ? '0 0 10px rgba(198, 153, 255, 0.5)' : 'none'; + progressBarRef.current.style.width = `${Math.min(100, Math.max(0, progress))}%`; } } - if (!isClickScrolling.current && headingElementsRef.current.length > 0) { let currentActiveId = null; - for (const { id, el } of headingElementsRef.current) { - const rect = el.getBoundingClientRect(); - if (rect.top <= 120) { - currentActiveId = id; - } else { - break; - } - } - - if (!currentActiveId && currentScrollY < 50) { - currentActiveId = headingElementsRef.current[0].id; - } - - if (currentActiveId) { - setActiveOutlineId((prev) => (prev !== currentActiveId ? currentActiveId : prev)); + if (el.getBoundingClientRect().top <= 120) currentActiveId = id; + else break; } + if (!currentActiveId && currentScrollY < 50) currentActiveId = headingElementsRef.current[0].id; + if (currentActiveId) setActiveOutlineId((prev) => (prev !== currentActiveId ? currentActiveId : prev)); } - ticking = false; }); ticking = true; } }; - window.addEventListener("scroll", handleScroll, { passive: true }); handleScroll(); - return () => window.removeEventListener("scroll", handleScroll); }, []); useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === "Escape") { - setCmdOpen(false); - return; - } - - const isModifier = event.metaKey || event.ctrlKey; - if (!isModifier || event.key.toLowerCase() !== "k") return; - - event.preventDefault(); - setCmdOpen((open) => !open); - }; - - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); - }, []); - - useEffect(() => { - setExpandedOutline((previous) => { - const next: Record = { ...previous }; + setExpandedOutline((prev) => { + const next: Record = { ...prev }; outlineGroups.forEach((group, index) => { - next[group.id] = index === 0 ? true : Boolean(previous[group.id]); + next[group.id] = index === 0 ? true : Boolean(prev[group.id]); }); return next; }); }, [outlineGroups]); const themeClasses = { - page: darkMode ? "bg-[#050505] text-[#F5F5F5]" : "bg-[#F5F3EE] text-[#111111]", - header: darkMode ? "bg-[#050505]/85" : "bg-[#fcfbf9]/85", - panel: darkMode ? "bg-[#050505]" : "bg-white", - border: darkMode ? "border-white/10" : "border-black/10", + page: darkMode ? "bg-[#050505] text-[#F5F5F5]" : "bg-[#FFFFFF] text-[#111111]", + sidebar: darkMode ? "bg-[#101010]" : "bg-[#F7F7F7]", + header: darkMode ? "bg-[#050505]/90" : "bg-[#FFFFFF]/90", + border: darkMode ? "border-[#222222]" : "border-[#E5E5E5]", muted: darkMode ? "text-zinc-400" : "text-zinc-500", - soft: darkMode ? "bg-[#0D0D0D] text-[#F5F5F5]" : "bg-[#F0EFEA] text-[#111111]", - active: darkMode ? "bg-[#111111] text-white" : "bg-white text-black", - accent: darkMode ? "text-zinc-100" : "text-zinc-800", - hoverAccent: darkMode ? "hover:text-white" : "hover:text-zinc-900", - input: darkMode ? "border-[#1D1D1D] bg-[#0B0B0B]" : "border-[#DDE0D7] bg-[#F7F6F3]", - sidebar: darkMode ? "bg-[#050505]" : "bg-[#F2F0EA]", - navItem: darkMode ? "text-[#F5F5F5]" : "text-[#111111]", + hoverAccent: darkMode ? "hover:text-[#C699FF]" : "hover:text-[#6f45d6]", + activeNavBg: darkMode ? "bg-[#C699FF]/15 text-[#C699FF]" : "bg-[#6f45d6]/10 text-[#6f45d6]", + inputBg: darkMode ? "bg-[#101010]" : "bg-[#F4F4F4]", }; const getTopicIcon = (topicId: string) => { @@ -307,25 +230,16 @@ export default function TopicLayout({ if (!id) return; const target = document.getElementById(id); if (!target) return; - isClickScrolling.current = true; setActiveOutlineId(id); - if (scrollTimeout.current) clearTimeout(scrollTimeout.current); - - const headerOffset = 88; - const top = target.getBoundingClientRect().top + window.scrollY - headerOffset; + const top = target.getBoundingClientRect().top + window.scrollY - 88; window.scrollTo({ top, behavior: "smooth" }); - scrollTimeout.current = setTimeout(() => { isClickScrolling.current = false; }, 800); }, []); - const scrollToTop = () => { - window.scrollTo({ top: 0, behavior: "smooth" }); - }; - const handleFeedback = (isPositive: boolean) => { setFeedbackSubmitted(true); if (isPositive) { @@ -338,101 +252,43 @@ export default function TopicLayout({ }; const currentTopicTitle = topics.find((t) => t.id === topicKey)?.title || frontmatter?.title || topicKey; + const activeHeadingTitle = activeOutlineId ? activeHeadings.find((h) => h.id === activeOutlineId)?.title : null; return ( -

+
+ +
+ + + + setCmdOpen(false)} searchData={searchData} onSelect={handleSearchSelect} placeholder="Search documentation or type a command..." /> + + {isMobileMenuOpen &&
setIsMobileMenuOpen(false)} />} -
- - - - setCmdOpen(false)} - searchData={searchData} - onSelect={handleSearchSelect} - placeholder="Search documentation or type a command..." - /> - - {isMobileMenuOpen && ( -
setIsMobileMenuOpen(false)} - /> - )} - -
-
-
- RefMe - docs +
+
+
+ RefMe + RefMe
- +
-
-
- -
- +
{topics.map((item) => { const isActive = item.id === topicKey; const TopicIcon = getTopicIcon(item.id); - return ( ); })} @@ -441,91 +297,45 @@ export default function TopicLayout({
-
-
- - -
- - R_ - -
-
- RefMe - docs +
+
+ +
+ RefMe Logo
+ RefMe
-
-
-
-
+
-
-
+ {/* Hero Section */} +
- - + + Read the RefMe Philosophy + @@ -361,7 +381,7 @@ export default function LandingPage() { />
- + Yash-Pluto @@ -396,7 +416,7 @@ export default function LandingPage() {
- Open PRs + Open PRs
{githubStats.openPrs}
@@ -404,7 +424,7 @@ export default function LandingPage() {
- Merged + Merged
{githubStats.mergedPrs}
@@ -412,7 +432,7 @@ export default function LandingPage() {
- Issues + Issues
{githubStats.openIssues}
@@ -420,7 +440,7 @@ export default function LandingPage() {
- Stars + Stars
{githubStats.stars}
@@ -490,111 +510,84 @@ export default function LandingPage() {
- {/* Refined 3-Step Process - Learning Centric */} -
-
+ + {/* Ultra-Premium 3-Step Architecture Flow */} +
+
-

- Three steps to master any tech stack. -

-

- Stop getting stuck in tutorial hell. Follow curated roadmaps, learn from high-quality videos, and reference syntax on the fly. +

+ Built for everyone who wants to learn

+

+ For students, professors, teachers, and developers. +

-
+
- {/* Step 1: Roadmaps */} -
- -
-
- - Frontend Path -
- Module 2 -
-
-
-
- HTML & CSS + {/* Horizontal Timeline Track (Desktop & Mobile aligned) */} +
+
+
Students
+
Educators
+
Developers
+
+ +
+
+
+
+
+
+
+ + {/* Vertical Stacked Cards Array */} +
+ +
+

Structured Roadmaps.

+
+
+ ✓ Step-by-step learning paths
-
-
- JavaScript Basics +
+ ✓ Master the topics listed below
-
-
- React Components +
+ ✓ Clear progression for all levels
- -
-
- 1 -
-
-

Pick your roadmap

-

- Whether you're a student or a senior dev, find the exact step-by-step path to learn Frontend, Backend, or DevOps. -

-
- {/* Step 2: Tutorials */} -
- -
-
-
- +
+

Video Tutorials.

+
+
+ ✓ Dedicated videos for every concept +
+
+ ✓ Visual explanations that stick +
+
+ ✓ Learn at your own pace
-
-

Understanding Server Components

-

12:45 • Next.js Advanced

-
-
- -
-
- 2 -
-
-

Watch & Learn

-

- Access hand-picked video tutorials and instantly reference the core syntax whenever you need it to bridge the gap. -

-
- {/* Step 3: Reference/Execute */} -
- -
-
- - fetchData.ts +
+

For Everyone.

+
+
+ ✓ Perfect for students & learners
-
- +
+ ✓ Resources for teachers & professors +
+
+ ✓ Quick reference for developers
-
-
- const fetchUser = async () ={'>'} {'{\n'} - {' '}const res = await fetch('/api/user');
- {' '}return res.json();\n - {'}'} -
- -
-
- 3
-

Copy & Build

-

- Put your knowledge into practice. Copy strictly-typed code examples and ship your projects without the boilerplate. -

+
From faf852c3b47c34fae4d805ccb8a6302ce72178db Mon Sep 17 00:00:00 2001 From: Yash Vardhan Date: Fri, 21 Aug 2026 02:44:11 +0530 Subject: [PATCH 10/14] chore: fix minor bug related to the Homepage UI --- frontend/app/[topic]/TopicLayout.tsx | 47 +---- frontend/app/components/Footer.tsx | 149 +++++++++++++ frontend/app/page.tsx | 304 +++++++++++++++++++-------- 3 files changed, 363 insertions(+), 137 deletions(-) create mode 100644 frontend/app/components/Footer.tsx diff --git a/frontend/app/[topic]/TopicLayout.tsx b/frontend/app/[topic]/TopicLayout.tsx index e6ad7ab..7df8bd1 100644 --- a/frontend/app/[topic]/TopicLayout.tsx +++ b/frontend/app/[topic]/TopicLayout.tsx @@ -32,6 +32,8 @@ import { Globe, } from "lucide-react"; +import Footer from "../components/Footer"; + export default function TopicLayout({ children, frontmatter, @@ -579,50 +581,7 @@ export default function TopicLayout({
- +
+ ); +} \ No newline at end of file diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index d9df744..e02bfd9 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,11 +1,13 @@ "use client"; -import { useState, useMemo, useEffect } from "react"; +import { useState, useMemo, useEffect, useRef } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useTheme } from "../src/context/ThemeContext"; import { FaGithub, FaLinkedin } from "react-icons/fa"; import SearchPalette, { useSearchOSKey, SearchItem } from "../app/components/SearchPalette"; +import { motion, AnimatePresence } from "framer-motion"; +import Footer from "./components/Footer"; import { BadgeCheck, @@ -33,6 +35,7 @@ export const REFERENCE_DATA = [ { category: "Core Languages", icon: , + desc: "Master foundational programming languages and concepts.", items: [ { name: "C++", href: "/cpp", icon: , desc: "Low-level systems, memory management, and STL patterns." }, { name: "JavaScript", href: "/javascript", icon: , desc: "Modern syntax, async flows, and browser fundamentals." }, @@ -47,6 +50,7 @@ export const REFERENCE_DATA = [ { category: "Frontend & Web", icon: , + desc: "Build responsive, accessible, and dynamic user interfaces.", items: [ { name: "React", href: "/react", icon: , desc: "Component lifecycles, state management, and effects." }, { name: "Next.js", href: "/nextjs", icon: , desc: "App router, SSR, static generation, and API routes." }, @@ -59,6 +63,7 @@ export const REFERENCE_DATA = [ { category: "Backend & Systems", icon: , + desc: "Design robust server architectures, databases, and APIs.", items: [ { name: "Bash", href: "/bash", icon: , desc: "Shell scripting, pipelines, and server automation." }, { name: "Node.js", href: "/nodejs", icon: , desc: "V8 runtime, event loop, and server-side TS/JS." }, @@ -71,6 +76,7 @@ export const REFERENCE_DATA = [ { category: "Concepts & Patterns", icon: , + desc: "Essential principles for scalable software design and security.", items: [ { name: "Async", href: "/async", icon: , desc: "Promises, event loops, and asynchronous scheduling." }, { name: "Testing", href: "/testing", icon: , desc: "Unit assertions, integration flows, and mocking." }, @@ -90,6 +96,7 @@ export const REFERENCE_DATA = [ { category: "Architecture & DevOps", icon: , + desc: "Deploy, monitor, scale, and manage cloud infrastructure.", items: [ { name: "Microservices", href: "/microservices", icon: , desc: "Service decoupling, bounded contexts, and API gateways." }, { name: "Event-Driven", href: "/event-driven", icon: , desc: "Message brokers, pub/sub, and eventual consistency." }, @@ -105,6 +112,7 @@ export const REFERENCE_DATA = [ { category: "Data & AI", icon: , + desc: "Explore machine learning, LLMs, and vector data pipelines.", items: [ { name: "Data Science", href: "/data-science", icon: , desc: "Statistical models, Jupyter notebooks, and pandas processing." }, { name: "Machine Learning", href: "/ml", icon: , desc: "Supervised training, neural networks, and model deployment." }, @@ -120,6 +128,7 @@ export const REFERENCE_DATA = [ { category: "Developer Tools", icon: , + desc: "Optimize your workflow with modern development and CI/CD tools.", items: [ { name: "VS Code", href: "/vscode", icon: , desc: "Workspace configuration, snippets, and integrated debugging." }, { name: "Linux", href: "/linux", icon: , desc: "Kernel architecture, system permissions, and POSIX standards." }, @@ -170,6 +179,10 @@ export default function LandingPage() { }); const [cycle, setCycle] = useState(0); + const [activeTab, setActiveTab] = useState(0); + const [isAutoPlaying, setIsAutoPlaying] = useState(true); + const [showScrollIndicator, setShowScrollIndicator] = useState(false); + const scrollContainerRef = useRef(null); const themeClasses = { page: darkMode ? "bg-[#0a0a0a] text-[#ededed]" : "bg-[#FFFFFF] text-[#111111]", @@ -247,6 +260,40 @@ export default function LandingPage() { return () => window.removeEventListener("keydown", handleKeyDown); }, []); + useEffect(() => { + if (!isAutoPlaying) return; + const interval = setInterval(() => { + setActiveTab((prev) => (prev + 1) % REFERENCE_DATA.length); + }, 5000); + return () => clearInterval(interval); + }, [isAutoPlaying]); + + const checkScroll = () => { + if (scrollContainerRef.current) { + const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; + setShowScrollIndicator( + Math.ceil(scrollHeight) > Math.ceil(clientHeight) + 5 && + Math.ceil(scrollTop + clientHeight) < Math.ceil(scrollHeight) - 20 + ); + } + }; + + useEffect(() => { + const container = scrollContainerRef.current; + if (!container) return; + + checkScroll(); + const timer = setTimeout(checkScroll, 600); + + const resizeObserver = new ResizeObserver(() => checkScroll()); + resizeObserver.observe(container); + + return () => { + clearTimeout(timer); + resizeObserver.disconnect(); + }; + }, [activeTab]); + const searchData = useMemo(() => { return REFERENCE_DATA.flatMap((cat) => cat.items.map((item) => ({ @@ -282,12 +329,55 @@ export default function LandingPage() { const currentBuild = dynamicBuildStats[cycle]; const currentActivity = dynamicActivityFeeds[cycle]; + const tabContentVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.08, + delayChildren: 0.1, + }, + }, + exit: { + opacity: 0, + transition: { duration: 0.15 } + } + }; + + const itemVariants = { + hidden: { opacity: 0, y: 15 }, + visible: { + opacity: 1, + y: 0, + transition: { + type: "spring", + stiffness: 400, + damping: 30 + } + }, + }; + return (
+