Skip to content
This repository was archived by the owner on Mar 2, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,21 @@ body {
@apply bg-background text-foreground;
}
}

@keyframes grid {
0% { transform: translateY(-50%); }
100% { transform: translateY(0); }
}
.animate-grid {
animation: grid 15s linear infinite;
}


@keyframes shine {
0% { transform: translateX(-150%) skewX(-12deg); }
100% { transform: translateX(150%) skewX(-12deg); }
}
.animate-shine {
animation: shine 3s infinite linear;
}

11 changes: 6 additions & 5 deletions app/pages/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getPageBySlug, getAllPages } from '@/lib/pages';
import ReactMarkdown from 'react-markdown';
import { notFound } from 'next/navigation';
import { LandingFooter } from "@/features/landing-page/components/footer";
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LandingFooter is imported but no longer used in this file. This will produce an unused import warning/error under common TS/ESLint configs; remove the import.

Suggested change
import { LandingFooter } from "@/features/landing-page/components/footer";

Copilot uses AI. Check for mistakes.
import { TextReveal } from '@/components/framer/text-reveal';

// This is required for static site generation with dynamic routes
export async function generateStaticParams() {
Expand All @@ -23,12 +24,12 @@ export default async function Page({ params }: { params: Promise<{ slug: string

return (
<>
<div className="space-y-2 mb-8">
<h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl capitalize">
{page.title}
</h1>
<div className="space-y-2 mb-8 relative">
<div className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl capitalize">
<TextReveal text={page.title} />
</div>
Comment on lines +28 to +30
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page replaces the <h1> with a <div>, which removes the semantic main heading for the page (accessibility/SEO regression). Prefer keeping the <h1> element and placing the TextReveal animation inside it so the document outline remains correct.

Suggested change
<div className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl capitalize">
<TextReveal text={page.title} />
</div>
<h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl capitalize">
<TextReveal text={page.title} />
</h1>

Copilot uses AI. Check for mistakes.
</div>
<div className="prose prose-zinc dark:prose-invert max-w-none prose-headings:scroll-m-20 prose-headings:tracking-tight prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-code:text-primary prose-code:bg-muted prose-code:px-1 prose-code:py-0.5 prose-code:rounded-sm">
<div className="relative z-10 prose prose-zinc dark:prose-invert max-w-none prose-headings:scroll-m-20 prose-headings:tracking-tight prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-code:text-primary prose-code:bg-muted prose-code:px-1 prose-code:py-0.5 prose-code:rounded-sm bg-card/10 backdrop-blur-sm p-4 rounded-xl border border-white/5">
<ReactMarkdown>{page.content}</ReactMarkdown>
</div>
</>
Expand Down
90 changes: 71 additions & 19 deletions app/pages/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import Link from 'next/link';
import { LandingFooter } from "@/features/landing-page/components/footer";
import { SidebarNav } from "@/components/sidebar-nav";
import { ScrollArea } from "@/components/ui/scroll-area";
import RetroGrid from "@/components/framer/retro-grid";
import DecryptedText from '@/components/framer/decrypted-text';
import { Button } from "@/components/ui/button";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import { Menu } from "lucide-react";

export default function PagesLayout({
children,
Expand All @@ -23,26 +29,72 @@ export default function PagesLayout({
}));

return (
<div className="flex min-h-screen flex-col bg-background">
<div className="container flex-1 items-start md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10">
<aside className="fixed top-20 z-30 -ml-2 hidden h-[calc(100vh-5rem)] w-full shrink-0 md:sticky md:block border-r border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<ScrollArea className="h-full pr-6 py-6 lg:py-8">
<div className="flex flex-col space-y-1 pl-4">
<h2 className="mb-2 px-2 text-lg font-semibold tracking-tight text-foreground">
Documentation
</h2>
<SidebarNav items={navItems} />
</div>
</ScrollArea>
</aside>
<main className="relative py-6 lg:gap-10 lg:py-8 lg:pr-10">
<div className="mx-auto w-full min-w-0 max-w-4xl px-4 lg:px-0">
{children}
</div>
</main>

<div className="relative flex flex-col min-h-[calc(100vh-5rem)] md:h-[calc(100vh-5rem)] bg-background/50 selection:bg-purple-500/30 overflow-hidden">
<div className="fixed inset-0 z-0 pointer-events-none">
<RetroGrid />
</div>

{/* Mobile Header */}
<div className="flex md:hidden items-center p-4 border-b border-white/10 relative z-20 bg-background/40 backdrop-blur-md">
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="mr-2">
<Menu className="h-5 w-5" />
</Button>
</SheetTrigger>
<SheetContent side="left" className="w-[80%] max-w-[300px] border-r-white/10 bg-background/95 backdrop-blur-xl pt-10">
<div className="h-full flex flex-col">
<h2 className="mb-6 px-4 text-lg font-bold tracking-tight text-foreground/80 uppercase">
<DecryptedText text="Documentation" />
</h2>
<ScrollArea className="flex-1 pr-6 -mr-6">
<div className="px-4 pb-10">
<SidebarNav items={navItems} />
</div>
</ScrollArea>
</div>
</SheetContent>
</Sheet>
<div className="font-bold text-lg tracking-tight">Docs</div>
</div>

{/* Desktop Resizable Layout */}
<div className="hidden md:flex flex-1 h-[calc(100vh-5rem)] z-10 relative">
<ResizablePanelGroup direction="horizontal" className="h-full w-full rounded-lg">
<ResizablePanel defaultSize={20} minSize={15} maxSize={30} className="border-r border-white/10 bg-background/30 backdrop-blur-xl">
<ScrollArea className="h-full py-6">
<div className="flex flex-col space-y-1 pl-6 pr-4">
<h2 className="mb-6 px-2 text-lg font-bold tracking-tight text-foreground/80 uppercase">
<DecryptedText text="Documentation" />
</h2>
<SidebarNav items={navItems} />
</div>
</ScrollArea>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={80}>
<ScrollArea className="h-full">
<div className="flex flex-col min-h-full">
<main className="relative flex-1 py-8 px-10">
<div className="mx-auto w-full min-w-0 max-w-4xl">
{children}
</div>
</main>
<LandingFooter />
</div>
</ScrollArea>
</ResizablePanel>
</ResizablePanelGroup>
</div>
<LandingFooter />

{/* Mobile Content Fallback */}
<div className="md:hidden flex-1 overflow-auto z-10 relative">
<main className="relative py-6 px-4">
{children}
</main>
<LandingFooter />
</div>
</div>
);
}

23 changes: 14 additions & 9 deletions app/pages/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { getAllPages } from '@/lib/pages';
import Link from 'next/link';
import { LandingFooter } from "@/features/landing-page/components/footer";
import { TextReveal } from "@/components/framer/text-reveal";
import SpotlightCard from "@/components/framer/spotlight";

export default function PagesIndex() {
const pages = getAllPages();

return (
<>
<div className="space-y-4">
<h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl">
Documentation
</h1>
<div className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl">
<TextReveal text="Documentation" />
</div>
Comment on lines +12 to +14
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page replaces the <h1> with a <div>, which removes the semantic top-level heading for the page (hurts accessibility and SEO). Keep an actual <h1> and render/animate TextReveal inside it so the heading semantics remain intact.

Suggested change
<div className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl">
<TextReveal text="Documentation" />
</div>
<h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl">
<TextReveal text="Documentation" />
</h1>

Copilot uses AI. Check for mistakes.
<p className="text-lg text-muted-foreground">
Welcome to the CodeVerse Hub documentation. Select a topic from the sidebar to get started.
</p>
Expand All @@ -20,12 +21,16 @@ export default function PagesIndex() {
<Link
key={page.slug}
href={`/pages/${page.slug}`}
className="group relative rounded-lg border p-6 hover:bg-muted/50 transition-colors"
className="block h-full group"
>
<h3 className="font-semibold leading-none tracking-tight group-hover:underline">
{page.title || page.slug}
</h3>
{/* You could extract an excerpt here if you wanted */}
<SpotlightCard className="h-full p-6 transition-colors hover:bg-muted/10 cursor-pointer bg-card/50 backdrop-blur-sm border-white/10 group-hover:border-purple-500/50" spotlightColor="rgba(139, 92, 246, 0.3)">
<h3 className="font-semibold leading-none tracking-tight mb-2 group-hover:text-purple-400 transition-colors">
{page.title || page.slug}
</h3>
<p className="text-sm text-muted-foreground">
Explore the {page.title || page.slug} section.
</p>
</SpotlightCard>
</Link>
))}
</div>
Expand Down
73 changes: 73 additions & 0 deletions components/framer/decrypted-text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
'use client';

import { useEffect, useState, useRef } from 'react';
import { motion } from 'motion/react';

const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";

interface DecryptedTextProps {
text: string;
speed?: number;
maxIterations?: number;
className?: string;
animateOnHover?: boolean;
revealDirection?: "start" | "end" | "center";
}

export default function DecryptedText({
text,
speed = 50,
maxIterations = 20,
className,
animateOnHover = true,
revealDirection = "start"
}: DecryptedTextProps) {
Comment on lines +8 to +24
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxIterations and revealDirection are exposed in the props and defaulted in the function signature, but they are never used. This makes the component API misleading and will typically trigger unused-variable lint/TS warnings. Either implement these options (e.g., cap iterations and support reveal direction) or remove them from the public props.

Copilot uses AI. Check for mistakes.
const [displayText, setDisplayText] = useState(text);
const [isScrambling, setIsScrambling] = useState(false);
const intervalRef = useRef<any>(null);

const scramble = () => {
if (isScrambling) return;
setIsScrambling(true);

let iteration = 0;

clearInterval(intervalRef.current);

intervalRef.current = setInterval(() => {
setDisplayText(
text
.split("")
.map((letter, index) => {
if (index < iteration) {
return text[index];
}
return letters[Math.floor(Math.random() * letters.length)];
})
.join("")
);

if (iteration >= text.length) {
clearInterval(intervalRef.current);
setIsScrambling(false);
}

iteration += 1 / 3;
}, speed);
};

useEffect(() => {
// Optional: Scramble on mount
// scramble();
return () => clearInterval(intervalRef.current);
}, []);
Comment on lines +25 to +63
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intervalRef is typed as any, and displayText is initialized from text but never updated if the text prop changes. This can lead to stale UI and makes it easy to miss interval cleanup issues. Prefer typing the ref as ReturnType<typeof setInterval> | null and add an effect to reset displayText (and clear any running interval) when text changes.

Copilot uses AI. Check for mistakes.

return (
<motion.span
className={className}
onMouseEnter={animateOnHover ? scramble : undefined}
>
{displayText}
</motion.span>
);
}
41 changes: 41 additions & 0 deletions components/framer/magnet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client';

import { useRef, useState } from 'react';
import { motion } from 'motion/react';

interface MagnetProps {
children: React.ReactNode;
magnetStrength?: number;
active?: boolean;
}

export default function Magnet({ children, magnetStrength = 2, active = false }: MagnetProps) {
const [position, setPosition] = useState({ x: 0, y: 0 });
Comment on lines +6 to +13
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This component uses React.ReactNode/React.MouseEvent types but never imports React (or import type React from "react"), which will fail TypeScript compilation. Also, the active prop is declared but unused; either implement its behavior or remove it to avoid a misleading API.

Copilot uses AI. Check for mistakes.
const ref = useRef<HTMLDivElement>(null);

const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
const { clientX, clientY } = e;
const { height, width, left, top } = ref.current!.getBoundingClientRect();
const middleX = clientX - (left + width / 2);
const middleY = clientY - (top + height / 2);
setPosition({ x: middleX, y: middleY });
};

const reset = () => {
setPosition({ x: 0, y: 0 });
};

const { x, y } = position;
return (
<motion.div
style={{ position: "relative", display: 'inline-block', width: '100%' }}
ref={ref}
onMouseMove={handleMouseMove}
onMouseLeave={reset}
animate={{ x: x / magnetStrength, y: y / magnetStrength }}
transition={{ type: "spring", stiffness: 150, damping: 15, mass: 0.1 }}
Comment on lines +30 to +36
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapper is hard-coded to width: '100%', which forces full-width layout wherever Magnet is used (e.g., SidebarNav in horizontal mode) and can cause overflow/spacing issues. Prefer letting the caller control sizing via className/style, or only apply w-full where it’s actually needed.

Copilot uses AI. Check for mistakes.
>
{children}
</motion.div>
);
}
37 changes: 37 additions & 0 deletions components/framer/retro-grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { cn } from "@/lib/utils";

export default function RetroGrid({
className,
angle = 65,
}: {
className?: string;
angle?: number;
}) {
return (
<div
className={cn(
"pointer-events-none absolute h-full w-full overflow-hidden opacity-50 [perspective:200px]",
className,
)}
style={{ "--grid-angle": `${angle}deg` } as React.CSSProperties}
>
Comment on lines +12 to +17
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file casts to React.CSSProperties but does not import React (or import type React from "react"), which will fail TypeScript compilation (Cannot find namespace 'React'). Add the missing type import or avoid the React. namespace by using CSSProperties imported from react.

Copilot uses AI. Check for mistakes.
{/* Grid */}
<div className="absolute inset-0 [transform:rotateX(var(--grid-angle))]">
<div
className={cn(
"animate-grid",
"[background-repeat:repeat] [background-size:60px_60px]",
"[height:300vh] [inset:0%_0px] [margin-left:-50%] [transform-origin:100%_0_0] [width:600vw]",

// User styles
"[background-image:linear-gradient(to_right,rgba(0,0,0,0.3)_1px,transparent_0),linear-gradient(to_bottom,rgba(0,0,0,0.3)_1px,transparent_0)]",
"dark:[background-image:linear-gradient(to_right,rgba(255,255,255,0.2)_1px,transparent_0),linear-gradient(to_bottom,rgba(255,255,255,0.2)_1px,transparent_0)]",
)}
/>
</div>

{/* Background Gradient */}
<div className="absolute inset-0 bg-gradient-to-t from-white to-transparent to-90% dark:from-black" />
</div>
);
}
Loading
Loading