└── Portfolio └── portfolio ├── components ├── OpenSource.tsx ├── additionalhook.tsx ├── ReachOut.tsx ├── ui │ ├── badge.tsx │ ├── button.tsx │ ├── card-spotlight.tsx │ ├── tracing-beam.tsx │ └── canvas-reveal-effect.tsx ├── magicui │ ├── blur-fade.tsx │ ├── icon-cloud.tsx │ ├── bento-grid.tsx │ ├── shimmer-button.tsx │ ├── dock.tsx │ └── particles.tsx ├── WorkExperience.tsx ├── connect.tsx ├── TechStack.tsx ├── ProjectCard.tsx ├── blogs.tsx ├── Aboutme.tsx └── Projects.tsx ├── .eslintrc.json ├── app ├── favicon.ico ├── layout.tsx ├── globals.css └── page.tsx ├── public ├── pfp.jpg ├── grid 3.avif ├── grid1.avif ├── grid2.webp ├── grid4.avif ├── grid5.avif ├── campussync.jpg ├── portfolio.jpg ├── 1--xbrainly.jpg ├── Rahul_Resume.pdf ├── Resume_rahul.pdf ├── deliverimage.jpg ├── insocialImage.jpg ├── chillguyanalyzer.png ├── vercel.svg └── next.svg ├── next.config.mjs ├── postcss.config.mjs ├── lib └── utils.ts ├── components.json ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md └── tailwind.config.ts /Portfolio/portfolio/components/OpenSource.tsx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Portfolio/portfolio/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /Portfolio/portfolio/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/app/favicon.ico -------------------------------------------------------------------------------- /Portfolio/portfolio/public/pfp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/pfp.jpg -------------------------------------------------------------------------------- /Portfolio/portfolio/public/grid 3.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/grid 3.avif -------------------------------------------------------------------------------- /Portfolio/portfolio/public/grid1.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/grid1.avif -------------------------------------------------------------------------------- /Portfolio/portfolio/public/grid2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/grid2.webp -------------------------------------------------------------------------------- /Portfolio/portfolio/public/grid4.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/grid4.avif -------------------------------------------------------------------------------- /Portfolio/portfolio/public/grid5.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/grid5.avif -------------------------------------------------------------------------------- /Portfolio/portfolio/public/campussync.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/campussync.jpg -------------------------------------------------------------------------------- /Portfolio/portfolio/public/portfolio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/portfolio.jpg -------------------------------------------------------------------------------- /Portfolio/portfolio/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /Portfolio/portfolio/public/1--xbrainly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/1--xbrainly.jpg -------------------------------------------------------------------------------- /Portfolio/portfolio/public/Rahul_Resume.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/Rahul_Resume.pdf -------------------------------------------------------------------------------- /Portfolio/portfolio/public/Resume_rahul.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/Resume_rahul.pdf -------------------------------------------------------------------------------- /Portfolio/portfolio/public/deliverimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/deliverimage.jpg -------------------------------------------------------------------------------- /Portfolio/portfolio/public/insocialImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/insocialImage.jpg -------------------------------------------------------------------------------- /Portfolio/portfolio/public/chillguyanalyzer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wraith2009/Portfolio/HEAD/Portfolio/portfolio/public/chillguyanalyzer.png -------------------------------------------------------------------------------- /Portfolio/portfolio/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /Portfolio/portfolio/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "magicui": "@/components/magicui" 18 | } 19 | } -------------------------------------------------------------------------------- /Portfolio/portfolio/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /Portfolio/portfolio/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Portfolio/portfolio/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /Portfolio/portfolio/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import "./globals.css"; 4 | import SocialDock from "@/components/connect"; 5 | import { Analytics } from "@vercel/analytics/react"; 6 | 7 | const inter = Inter({ subsets: ["latin"] }); 8 | 9 | export const metadata: Metadata = { 10 | title: "Rahul Bhardwaj", 11 | description: "Rahul's Portfolio", 12 | }; 13 | 14 | export default function RootLayout({ 15 | children, 16 | }: Readonly<{ 17 | children: React.ReactNode; 18 | }>) { 19 | return ( 20 | 21 | 22 | 23 | {children} 24 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/additionalhook.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, RefObject } from "react"; 2 | 3 | export function useOnScreen(ref: RefObject): boolean { 4 | const [isIntersecting, setIntersecting] = useState(false); 5 | 6 | useEffect(() => { 7 | const observer = new IntersectionObserver( 8 | ([entry]) => setIntersecting(entry.isIntersecting), 9 | { threshold: 0.1 } // Adjust this threshold as needed 10 | ); 11 | 12 | const currentRef = ref.current; 13 | 14 | if (currentRef) { 15 | observer.observe(currentRef); 16 | } 17 | 18 | return () => { 19 | if (currentRef) { 20 | observer.unobserve(currentRef); 21 | } 22 | }; 23 | }, [ref]); 24 | 25 | return isIntersecting; 26 | } 27 | -------------------------------------------------------------------------------- /Portfolio/portfolio/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "portfolio", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@heroicons/react": "^2.2.0", 13 | "@radix-ui/react-icons": "^1.3.0", 14 | "@radix-ui/react-slot": "^1.1.0", 15 | "@react-three/fiber": "^8.17.7", 16 | "@vercel/analytics": "^1.3.1", 17 | "class-variance-authority": "^0.7.0", 18 | "clsx": "^2.1.1", 19 | "framer-motion": "^11.11.9", 20 | "next": "14.2.5", 21 | "next-themes": "^0.3.0", 22 | "react": "^18", 23 | "react-dom": "^18", 24 | "react-icon-cloud": "^4.1.4", 25 | "react-icons": "^5.4.0", 26 | "tailwind-merge": "^2.5.4", 27 | "tailwindcss-animate": "^1.0.7", 28 | "three": "^0.168.0" 29 | }, 30 | "devDependencies": { 31 | "@types/node": "^20", 32 | "@types/react": "^18", 33 | "@types/react-dom": "^18", 34 | "@types/three": "^0.168.0", 35 | "eslint": "^8", 36 | "eslint-config-next": "14.2.5", 37 | "postcss": "^8", 38 | "tailwindcss": "^3.4.1", 39 | "typescript": "^5" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ReachOut.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | // export default function ReachOut(){ 4 | // return ( 5 | //
6 | //

7 | // Thank you for visiting my portfolio! 8 | //

9 | //

10 | // If you’re looking for someone to help bring your ideas to life, I’d be excited to collaborate with you. Whether you need a creative solution, technical expertise, or someone to work closely with your team, I’m here to contribute in any way I can. 11 | //

12 | //

13 | // Feel free to reach out if you’re interested in hiring me or partnering on a project. 14 | //

15 | //

16 | // You can contact me at rbh97995@gmail.com . 17 | //

18 | //

19 | // I look forward to seeing how we can create something great together! 20 | //

21 | //
22 | // ) 23 | // } -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { cva, type VariantProps } from "class-variance-authority" 3 | 4 | import { cn } from "@/lib/utils" 5 | 6 | const badgeVariants = cva( 7 | "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", 8 | { 9 | variants: { 10 | variant: { 11 | default: 12 | "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", 13 | secondary: 14 | "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", 15 | destructive: 16 | "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", 17 | outline: "text-foreground", 18 | }, 19 | }, 20 | defaultVariants: { 21 | variant: "default", 22 | }, 23 | } 24 | ) 25 | 26 | export interface BadgeProps 27 | extends React.HTMLAttributes, 28 | VariantProps {} 29 | 30 | function Badge({ className, variant, ...props }: BadgeProps) { 31 | return ( 32 |
33 | ) 34 | } 35 | 36 | export { Badge, badgeVariants } -------------------------------------------------------------------------------- /Portfolio/portfolio/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Portfolio/portfolio/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/magicui/blur-fade.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useRef } from "react"; 4 | import { 5 | AnimatePresence, 6 | motion, 7 | useInView, 8 | UseInViewOptions, 9 | Variants, 10 | } from "framer-motion"; 11 | 12 | type MarginType = UseInViewOptions["margin"]; 13 | 14 | interface BlurFadeProps { 15 | children: React.ReactNode; 16 | className?: string; 17 | variant?: { 18 | hidden: { y: number }; 19 | visible: { y: number }; 20 | }; 21 | duration?: number; 22 | delay?: number; 23 | yOffset?: number; 24 | inView?: boolean; 25 | inViewMargin?: MarginType; 26 | blur?: string; 27 | } 28 | 29 | export default function BlurFade({ 30 | children, 31 | className, 32 | variant, 33 | duration = 0.4, 34 | delay = 0, 35 | yOffset = 6, 36 | inView = false, 37 | inViewMargin = "-50px", 38 | blur = "6px", 39 | }: BlurFadeProps) { 40 | const ref = useRef(null); 41 | const inViewResult = useInView(ref, { once: true, margin: inViewMargin }); 42 | const isInView = !inView || inViewResult; 43 | const defaultVariants: Variants = { 44 | hidden: { y: yOffset, opacity: 0, filter: `blur(${blur})` }, 45 | visible: { y: -yOffset, opacity: 1, filter: `blur(0px)` }, 46 | }; 47 | const combinedVariants = variant || defaultVariants; 48 | return ( 49 | 50 | 63 | {children} 64 | 65 | 66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/WorkExperience.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { HiMiniBuildingOffice2 } from "react-icons/hi2"; 3 | interface WorkExperienceProps { 4 | position: string; 5 | companyName: string; 6 | timePeriod: string; 7 | } 8 | 9 | const WorkExperience: React.FC = ({ 10 | position, 11 | companyName, 12 | timePeriod, 13 | }) => { 14 | return ( 15 |
16 |
17 |

{companyName}

18 |

{position}

19 |

{timePeriod}

20 |
21 |
22 | ); 23 | }; 24 | 25 | export default function MyWorkExperience() { 26 | return ( 27 |
28 |
29 |

Work Experience

30 | 31 |

Places I have worked at

32 |
33 |
34 | 39 | 40 | 45 | 46 | 51 | 52 | 57 |
58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/connect.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { FaEnvelope, FaTwitter, FaGithub, FaHome } from "react-icons/fa"; 4 | import { Dock, DockIcon } from "./magicui/dock"; 5 | 6 | export default function SocialDock() { 7 | return ( 8 |
9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | {/* 44 | 49 | 50 | 51 | */} 52 | 53 | 54 | 59 | 60 | 61 | 62 | 63 |
64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /Portfolio/portfolio/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --background: 0 0% 100%; 8 | --foreground: 240 10% 3.9%; 9 | --card: 0 0% 100%; 10 | --card-foreground: 240 10% 3.9%; 11 | --popover: 0 0% 100%; 12 | --popover-foreground: 240 10% 3.9%; 13 | --primary: 240 5.9% 10%; 14 | --primary-foreground: 0 0% 98%; 15 | --secondary: 240 4.8% 95.9%; 16 | --secondary-foreground: 240 5.9% 10%; 17 | --muted: 240 4.8% 95.9%; 18 | --muted-foreground: 240 3.8% 46.1%; 19 | --accent: 240 4.8% 95.9%; 20 | --accent-foreground: 240 5.9% 10%; 21 | --destructive: 0 84.2% 60.2%; 22 | --destructive-foreground: 0 0% 98%; 23 | --border: 240 5.9% 90%; 24 | --input: 240 5.9% 90%; 25 | --ring: 240 10% 3.9%; 26 | --radius: 0.5rem; 27 | --chart-1: 12 76% 61%; 28 | --chart-2: 173 58% 39%; 29 | --chart-3: 197 37% 24%; 30 | --chart-4: 43 74% 66%; 31 | --chart-5: 27 87% 67%; 32 | } 33 | 34 | .dark { 35 | --background: 240 10% 3.9%; 36 | --foreground: 0 0% 98%; 37 | --card: 240 10% 3.9%; 38 | --card-foreground: 0 0% 98%; 39 | --popover: 240 10% 3.9%; 40 | --popover-foreground: 0 0% 98%; 41 | --primary: 0 0% 98%; 42 | --primary-foreground: 240 5.9% 10%; 43 | --secondary: 240 3.7% 15.9%; 44 | --secondary-foreground: 0 0% 98%; 45 | --muted: 240 3.7% 15.9%; 46 | --muted-foreground: 240 5% 64.9%; 47 | --accent: 240 3.7% 15.9%; 48 | --accent-foreground: 0 0% 98%; 49 | --destructive: 0 62.8% 30.6%; 50 | --destructive-foreground: 0 0% 98%; 51 | --border: 240 3.7% 15.9%; 52 | --input: 240 3.7% 15.9%; 53 | --ring: 240 4.9% 83.9%; 54 | --chart-1: 220 70% 50%; 55 | --chart-2: 160 60% 45%; 56 | --chart-3: 30 80% 55%; 57 | --chart-4: 280 65% 60%; 58 | --chart-5: 340 75% 55%; 59 | } 60 | } 61 | 62 | @layer base { 63 | * { 64 | @apply border-border; 65 | } 66 | body { 67 | @apply bg-background text-foreground; 68 | } 69 | } -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "bg-primary text-primary-foreground shadow hover:bg-primary/90", 14 | destructive: 15 | "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", 16 | outline: 17 | "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", 18 | secondary: 19 | "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", 20 | ghost: "hover:bg-accent hover:text-accent-foreground", 21 | link: "text-primary underline-offset-4 hover:underline", 22 | }, 23 | size: { 24 | default: "h-9 px-4 py-2", 25 | sm: "h-8 rounded-md px-3 text-xs", 26 | lg: "h-10 rounded-md px-8", 27 | icon: "h-9 w-9", 28 | }, 29 | }, 30 | defaultVariants: { 31 | variant: "default", 32 | size: "default", 33 | }, 34 | } 35 | ) 36 | 37 | export interface ButtonProps 38 | extends React.ButtonHTMLAttributes, 39 | VariantProps { 40 | asChild?: boolean 41 | } 42 | 43 | const Button = React.forwardRef( 44 | ({ className, variant, size, asChild = false, ...props }, ref) => { 45 | const Comp = asChild ? Slot : "button" 46 | return ( 47 | 52 | ) 53 | } 54 | ) 55 | Button.displayName = "Button" 56 | 57 | export { Button, buttonVariants } 58 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/TechStack.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import IconCloud from "./magicui/icon-cloud"; 4 | import BlurFade from "./magicui/blur-fade"; // Use the IconCloud component you've defined 5 | import { i } from "framer-motion/client"; 6 | import { Badge } from "./ui/badge"; 7 | 8 | const BLUR_FADE_DELAY = 0.04; 9 | export default function TechStackSection() { 10 | const techStackIcons = [ 11 | "typescript", 12 | "javascript", 13 | "dart", 14 | "java", 15 | "rust", 16 | "react", 17 | "nextdotjs", 18 | "linux", 19 | "flutter", 20 | "android", 21 | "html5", 22 | "css3", 23 | "nodedotjs", 24 | "express", 25 | "prisma", 26 | "postgresql", 27 | "docker", 28 | "firebase", 29 | "vercel", 30 | "testinglibrary", 31 | "jest", 32 | "cypress", 33 | "docker", 34 | "git", 35 | "mongodb", 36 | "mysql", 37 | "github", 38 | "visualstudiocode", 39 | "figma", 40 | ]; 41 | 42 | const skills = [ 43 | "React", 44 | "Next.js", 45 | "Typescript", 46 | "Node.js", 47 | "Postgres", 48 | "MongoDB", 49 | "Express", 50 | "C++", 51 | "git", 52 | "GitHub", 53 | "Javascript", 54 | ]; 55 | 56 | return ( 57 |
58 |

59 | My Tech Stacks 60 |

61 | 62 |
63 | 64 |

Skills

65 |
66 |
67 | {skills.map((skill, id) => ( 68 | 69 | {skill} 70 | 71 | ))} 72 |
73 |
74 |
75 | 76 |
77 |
78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ProjectCard.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { FiGithub, FiLink2 } from "react-icons/fi"; 3 | import Image from "next/image"; 4 | import { Badge } from "./ui/badge"; 5 | 6 | interface FeaturedProjectComponentProps { 7 | imageSrc?: string; 8 | projectName: string; 9 | description: string; 10 | technologies: string[]; 11 | github: string; 12 | live: string; 13 | } 14 | 15 | const FeaturedProjectComponent: React.FC = ({ 16 | imageSrc, 17 | projectName, 18 | description, 19 | technologies, 20 | github, 21 | live, 22 | }) => { 23 | const [isExpanded, setIsExpanded] = useState(false); 24 | 25 | return ( 26 |
27 |
28 |

29 | {projectName} 30 |

31 |

36 | {description} 37 |

38 | 39 |
40 | {technologies.map((tech, index) => ( 41 | {tech} 42 | ))} 43 |
44 | 66 |
67 |
68 | ); 69 | }; 70 | 71 | export default FeaturedProjectComponent; 72 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/magicui/icon-cloud.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect, useMemo, useState } from "react"; 4 | import { useTheme } from "next-themes"; 5 | import { 6 | Cloud, 7 | fetchSimpleIcons, 8 | ICloud, 9 | renderSimpleIcon, 10 | SimpleIcon, 11 | } from "react-icon-cloud"; 12 | 13 | export const cloudProps: Omit = { 14 | containerProps: { 15 | style: { 16 | display: "flex", 17 | justifyContent: "center", 18 | alignItems: "center", 19 | width: "100%", 20 | paddingTop: 40, 21 | }, 22 | }, 23 | options: { 24 | reverse: true, 25 | depth: 1, 26 | wheelZoom: false, 27 | imageScale: 2, 28 | activeCursor: "default", 29 | tooltip: "native", 30 | initial: [0.1, -0.1], 31 | clickToFront: 500, 32 | tooltipDelay: 0, 33 | outlineColour: "#0000", 34 | maxSpeed: 0.04, 35 | minSpeed: 0.02, 36 | // dragControl: false, 37 | }, 38 | }; 39 | 40 | export const renderCustomIcon = (icon: SimpleIcon, theme: string) => { 41 | const bgHex = theme === "light" ? "#f3f2ef" : "#080510"; 42 | const fallbackHex = theme === "light" ? "#6e6e73" : "#ffffff"; 43 | const minContrastRatio = theme === "dark" ? 2 : 1.2; 44 | 45 | return renderSimpleIcon({ 46 | icon, 47 | bgHex, 48 | fallbackHex, 49 | minContrastRatio, 50 | size: 42, 51 | aProps: { 52 | href: undefined, 53 | target: undefined, 54 | rel: undefined, 55 | onClick: (e: any) => e.preventDefault(), 56 | }, 57 | }); 58 | }; 59 | 60 | export type DynamicCloudProps = { 61 | iconSlugs: string[]; 62 | }; 63 | 64 | type IconData = Awaited>; 65 | 66 | export default function IconCloud({ iconSlugs }: DynamicCloudProps) { 67 | const [data, setData] = useState(null); 68 | const { theme } = useTheme(); 69 | 70 | useEffect(() => { 71 | fetchSimpleIcons({ slugs: iconSlugs }).then(setData); 72 | }, [iconSlugs]); 73 | 74 | const renderedIcons = useMemo(() => { 75 | if (!data) return null; 76 | 77 | return Object.values(data.simpleIcons).map((icon) => 78 | renderCustomIcon(icon, theme || "light"), 79 | ); 80 | }, [data, theme]); 81 | 82 | return ( 83 | // @ts-ignore 84 | 85 | <>{renderedIcons} 86 | 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ui/card-spotlight.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useMotionValue, motion, useMotionTemplate } from "framer-motion"; 4 | import React, { MouseEvent as ReactMouseEvent, useState } from "react"; 5 | import { CanvasRevealEffect } from "@/components/ui/canvas-reveal-effect"; 6 | import { cn } from "@/lib/utils"; 7 | 8 | export const CardSpotlight = ({ 9 | children, 10 | radius = 350, 11 | color = "#262626", 12 | className, 13 | ...props 14 | }: { 15 | radius?: number; 16 | color?: string; 17 | children: React.ReactNode; 18 | } & React.HTMLAttributes) => { 19 | const mouseX = useMotionValue(0); 20 | const mouseY = useMotionValue(0); 21 | function handleMouseMove({ 22 | currentTarget, 23 | clientX, 24 | clientY, 25 | }: ReactMouseEvent) { 26 | let { left, top } = currentTarget.getBoundingClientRect(); 27 | 28 | mouseX.set(clientX - left); 29 | mouseY.set(clientY - top); 30 | } 31 | 32 | const [isHovering, setIsHovering] = useState(false); 33 | const handleMouseEnter = () => setIsHovering(true); 34 | const handleMouseLeave = () => setIsHovering(false); 35 | return ( 36 |
46 | 59 | {isHovering && ( 60 | 69 | )} 70 | 71 | {children} 72 |
73 | ); 74 | }; 75 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/blogs.tsx: -------------------------------------------------------------------------------- 1 | export default function Blogs_section() { 2 | const blogs = [ 3 | { 4 | date: "Mar 08, 2025", 5 | title: "How vector search works", 6 | link: "https://medium.com/@rbh97995/how-vector-search-works-1f965e167a63", 7 | }, 8 | { 9 | date: "May 08, 2025", 10 | title: "Understanding Phantom Reads: Ghosts in Your Database", 11 | link: "https://medium.com/@rbh97995/understanding-phantom-reads-ghosts-in-your-database-2e2964caf96b", 12 | }, 13 | { 14 | date: "May 25, 2025", 15 | title: 16 | "Eventual Consistency in Distributed Systems: A Real-World Perspective", 17 | link: "https://medium.com/@rbh97995/eventual-consistency-in-distributed-systems-a-real-world-perspective-1175fd0f742b", 18 | }, 19 | { 20 | date: "June 2, 2025", 21 | title: 22 | "From Monolith to Microservice: Designing a Centralized Payment System for a Growing EdTech Platform", 23 | link: "https://medium.com/@rbh97995/from-monolith-to-microservice-designing-a-centralized-payment-system-for-a-growing-edtech-platform-23539a4d89ff", 24 | }, 25 | { 26 | date: "June 30, 2025", 27 | title: 28 | "Understanding Processes in Operating Systems: The Beating Heart of Your Computer", 29 | link: "https://medium.com/@rbh97995/understanding-processes-in-operating-systems-the-beating-heart-of-your-computer-ae1734a57392", 30 | }, 31 | { 32 | date: "July 07, 2025", 33 | title: "How Computers Talk: A Deep Dive into Host-to-Host Communication", 34 | link: "https://medium.com/@rahulbhardwaj09/how-computers-talk-a-deep-dive-into-host-to-host-communication-2210494ea0fa", 35 | }, 36 | ]; 37 | 38 | return ( 39 |
40 |
41 |
42 |

Recent blog posts

43 |
44 |

Things I have written recently.

45 |
    46 | {blogs.map((blog, index) => ( 47 |
  • 48 | 49 | 50 | {blog.date} : 51 | 52 | 58 | {blog.title} 59 | 60 |
  • 61 | ))} 62 |
63 |
64 |
65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/magicui/bento-grid.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from "react"; 2 | import { ArrowRightIcon } from "@radix-ui/react-icons"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | import { Button } from "@/components/ui/button"; 6 | 7 | const BentoGrid = ({ 8 | children, 9 | className, 10 | }: { 11 | children: ReactNode; 12 | className?: string; 13 | }) => { 14 | return ( 15 |
21 | {children} 22 |
23 | ); 24 | }; 25 | 26 | const BentoCard = ({ 27 | name, 28 | className, 29 | background, 30 | Icon, 31 | description, 32 | img, 33 | imgClassName, 34 | href, 35 | cta, 36 | }: { 37 | name: string; 38 | className: string; 39 | background: ReactNode; 40 | Icon: any; 41 | description: string; 42 | img?: string; 43 | imgClassName?: string; 44 | href: string; 45 | cta: string; 46 | }) => ( 47 |
58 |
59 | {img && ( 60 | {img} 65 | )} 66 |
67 |
68 | 69 |

70 | {name} 71 |

72 |

{description}

73 |
74 | 75 |
80 | 86 |
87 |
88 |
89 | ); 90 | 91 | export { BentoCard, BentoGrid }; 92 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/Aboutme.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { BentoGrid, BentoCard } from "./magicui/bento-grid"; 4 | import { FaEnvelope, FaLink, FaUserTie, FaLaptopCode } from "react-icons/fa"; 5 | 6 | const About = () => { 7 | return ( 8 |
9 |

10 | About Me 11 |

12 | 13 | 14 | 19 | } 20 | Icon={FaUserTie} 21 | img="/grid4.avif" 22 | imgClassName="w-full h-full" 23 | description="A Software Developer with almost 1 year of experience. I specialize in MERN stack development and am passionate about creating innovative technologies." 24 | href="https://www.linkedin.com/in/rahulbhardwaj09/" 25 | cta="Read more" 26 | /> 27 | 28 | 33 | } 34 | Icon={FaLaptopCode} 35 | img="/grid 3.avif" 36 | imgClassName="w-full h-full" 37 | description="With experience working with clients and companies, I focus on building full-stack applications that deliver seamless user experiences." 38 | href="https://github.com/wraith2009" 39 | cta="See My Work" 40 | /> 41 | 42 | 47 | } 48 | Icon={FaLink} 49 | img="/grid 3.avif" 50 | imgClassName="w-full h-full" 51 | description="I am always looking to collaborate on new and exciting projects. Whether it is for technical expertise or creative solutions, I am ready to contribute." 52 | href="https://x.com/10xRahul_" 53 | cta="Contact Me" 54 | /> 55 | 56 | 61 | } 62 | Icon={FaEnvelope} 63 | img="/grid5.avif" 64 | imgClassName="w-full h-full" 65 | description="Feel free to reach out via email if you want to hire me or collaborate on a project. Let us create something amazing together!" 66 | href="mailto:rbh97995@gmail.com" 67 | cta="Send Mail" 68 | /> 69 | 70 |
71 | ); 72 | }; 73 | 74 | export default About; 75 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/magicui/shimmer-button.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface ShimmerButtonProps 6 | extends React.ButtonHTMLAttributes { 7 | shimmerColor?: string; 8 | shimmerSize?: string; 9 | borderRadius?: string; 10 | shimmerDuration?: string; 11 | background?: string; 12 | className?: string; 13 | children?: React.ReactNode; 14 | } 15 | 16 | const ShimmerButton = React.forwardRef( 17 | ( 18 | { 19 | shimmerColor = "#ffffff", 20 | shimmerSize = "0.05em", 21 | shimmerDuration = "3s", 22 | borderRadius = "100px", 23 | background = "rgba(0, 0, 0, 1)", 24 | className, 25 | children, 26 | ...props 27 | }, 28 | ref, 29 | ) => { 30 | return ( 31 | 90 | ); 91 | }, 92 | ); 93 | 94 | ShimmerButton.displayName = "ShimmerButton"; 95 | 96 | export default ShimmerButton; 97 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/magicui/dock.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { PropsWithChildren, useRef } from "react"; 4 | import { cva, type VariantProps } from "class-variance-authority"; 5 | import { motion, useMotionValue, useSpring, useTransform } from "framer-motion"; 6 | 7 | import { cn } from "@/lib/utils"; 8 | 9 | export interface DockProps extends VariantProps { 10 | className?: string; 11 | magnification?: number; 12 | distance?: number; 13 | direction?: "top" | "middle" | "bottom"; 14 | children: React.ReactNode; 15 | } 16 | 17 | const DEFAULT_MAGNIFICATION = 60; 18 | const DEFAULT_DISTANCE = 140; 19 | 20 | const dockVariants = cva( 21 | "mx-auto w-max mt-8 h-[58px] p-2 flex gap-2 rounded-2xl border supports-backdrop-blur:bg-white/10 supports-backdrop-blur:dark:bg-black/10 backdrop-blur-md", 22 | ); 23 | 24 | const Dock = React.forwardRef( 25 | ( 26 | { 27 | className, 28 | children, 29 | magnification = DEFAULT_MAGNIFICATION, 30 | distance = DEFAULT_DISTANCE, 31 | direction = "bottom", 32 | ...props 33 | }, 34 | ref, 35 | ) => { 36 | const mousex = useMotionValue(Infinity); 37 | 38 | const renderChildren = () => { 39 | return React.Children.map(children, (child: any) => { 40 | return React.cloneElement(child, { 41 | mousex: mousex, 42 | magnification: magnification, 43 | distance: distance, 44 | }); 45 | }); 46 | }; 47 | 48 | return ( 49 | mousex.set(e.pageX)} 52 | onMouseLeave={() => mousex.set(Infinity)} 53 | {...props} 54 | className={cn(dockVariants({ className }), { 55 | "items-start": direction === "top", 56 | "items-center": direction === "middle", 57 | "items-end": direction === "bottom", 58 | })} 59 | > 60 | {renderChildren()} 61 | 62 | ); 63 | }, 64 | ); 65 | 66 | Dock.displayName = "Dock"; 67 | 68 | export interface DockIconProps { 69 | size?: number; 70 | magnification?: number; 71 | distance?: number; 72 | mousex?: any; 73 | className?: string; 74 | children?: React.ReactNode; 75 | props?: PropsWithChildren; 76 | } 77 | 78 | const DockIcon = ({ 79 | size, 80 | magnification = DEFAULT_MAGNIFICATION, 81 | distance = DEFAULT_DISTANCE, 82 | mousex, 83 | className, 84 | children, 85 | ...props 86 | }: DockIconProps) => { 87 | const ref = useRef(null); 88 | 89 | const distanceCalc = useTransform(mousex, (val: number) => { 90 | const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 }; 91 | 92 | return val - bounds.x - bounds.width / 2; 93 | }); 94 | 95 | let widthSync = useTransform( 96 | distanceCalc, 97 | [-distance, 0, distance], 98 | [40, magnification, 40], 99 | ); 100 | 101 | let width = useSpring(widthSync, { 102 | mass: 0.1, 103 | stiffness: 150, 104 | damping: 12, 105 | }); 106 | 107 | return ( 108 | 117 | {children} 118 | 119 | ); 120 | }; 121 | 122 | DockIcon.displayName = "DockIcon"; 123 | 124 | export { Dock, DockIcon, dockVariants }; 125 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/Projects.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useRef } from "react"; 4 | import ProjectComponent from "./ProjectCard"; 5 | import { useOnScreen } from "./additionalhook"; 6 | 7 | const Projects: React.FC = () => { 8 | const projectsRef = useRef(null); 9 | const isVisible = useOnScreen(projectsRef); 10 | 11 | const projectData = [ 12 | { 13 | projectName: "w-Monitor", 14 | description: 15 | "Currently in the building phase, A modern website and API monitoring platform with alerting.", 16 | technologies: [ 17 | "React.js", 18 | "TypeScript", 19 | "Tailwind CSS", 20 | "SQS", 21 | "AWS Lambda", 22 | ], 23 | github: "https://github.com/wraith2009/w-monitor-backend", 24 | live: "#", // In building phase 25 | }, 26 | { 27 | projectName: "ts-orm", 28 | description: 29 | " Currently in active development . A TypeScript-first ORM designed for fun.", 30 | technologies: ["TypeScript", "Node.js", "PostgreSQL", "Zod"], 31 | github: "https://github.com/wraith2009/ts-orm", 32 | live: "#", // In building phase 33 | }, 34 | { 35 | projectName: "100xBrainly", 36 | description: 37 | "A personal Secound Brain with AI feature to communicate with your secound brain.", 38 | technologies: [ 39 | "React.js", 40 | "TypeScript", 41 | "Tailwind CSS", 42 | "ExpressJs", 43 | "Node.js", 44 | "Recoil", 45 | ], 46 | github: "https://github.com/wraith2009/brainlyFrontend", 47 | live: "https://brainly-frontend-sable.vercel.app/", 48 | }, 49 | 50 | { 51 | projectName: "inSocial", 52 | description: "A social media platform with real time messaging.", 53 | technologies: [ 54 | "Node.js", 55 | "Express", 56 | "React.js", 57 | "Tailwind CSS", 58 | "WebSockets", 59 | "MongoDB", 60 | "Google Gemini", 61 | ], 62 | github: "https://github.com/mayank2153/inSocial", 63 | live: "#", 64 | }, 65 | { 66 | projectName: "ChillGuyAnalyzer", 67 | description: 68 | "A fun project that i worked on . It measure the chillness of a person using AI based on their Github profile.", 69 | technologies: [ 70 | "React.js", 71 | "TypeScript", 72 | "Tailwind CSS", 73 | "Honojs", 74 | "OpenAI", 75 | ], 76 | github: "https://github.com/wraith2009/ChillGuyAnalyzer", 77 | live: "https://chillguyanalyzer.onrender.com/", 78 | }, 79 | ]; 80 | 81 | return ( 82 |
89 |

90 | Projects 91 |

92 |
93 | {projectData.map((project, index) => ( 94 | 102 | ))} 103 |
104 |
105 | ); 106 | }; 107 | 108 | export default Projects; 109 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ui/tracing-beam.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React, { useEffect, useRef, useState } from "react"; 3 | import { 4 | motion, 5 | useTransform, 6 | useScroll, 7 | useVelocity, 8 | useSpring, 9 | } from "framer-motion"; 10 | import { cn } from "@/lib/utils"; 11 | 12 | export const TracingBeam = ({ 13 | children, 14 | className, 15 | }: { 16 | children: React.ReactNode; 17 | className?: string; 18 | }) => { 19 | const ref = useRef(null); 20 | const { scrollYProgress } = useScroll({ 21 | target: ref, 22 | offset: ["start start", "end start"], 23 | }); 24 | 25 | const contentRef = useRef(null); 26 | const [svgHeight, setSvgHeight] = useState(0); 27 | 28 | useEffect(() => { 29 | if (contentRef.current) { 30 | setSvgHeight(contentRef.current.offsetHeight); 31 | } 32 | }, []); 33 | 34 | const y1 = useSpring( 35 | useTransform(scrollYProgress, [0, 0.8], [50, svgHeight]), 36 | { 37 | stiffness: 500, 38 | damping: 90, 39 | } 40 | ); 41 | const y2 = useSpring( 42 | useTransform(scrollYProgress, [0, 1], [50, svgHeight - 200]), 43 | { 44 | stiffness: 500, 45 | damping: 90, 46 | } 47 | ); 48 | 49 | return ( 50 | 54 |
55 | 0 63 | ? "none" 64 | : "rgba(0, 0, 0, 0.24) 0px 3px 8px", 65 | }} 66 | className="ml-[27px] h-4 w-4 rounded-full border border-netural-200 shadow-sm flex items-center justify-center" 67 | > 68 | 0 ? "white" : "var(--emerald-500)", 76 | borderColor: 77 | scrollYProgress.get() > 0 ? "white" : "var(--emerald-600)", 78 | }} 79 | className="h-2 w-2 rounded-full border border-neutral-300 bg-white" 80 | /> 81 | 82 | 124 |
125 |
{children}
126 |
127 | ); 128 | }; 129 | -------------------------------------------------------------------------------- /Portfolio/portfolio/app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; // <-- This ensures everything runs on the client-side 2 | 3 | import { motion } from "framer-motion"; 4 | import ShimmerButton from "@/components/magicui/shimmer-button"; 5 | import TechStackSection from "@/components/TechStack"; 6 | import MyProjects from "@/components/Projects"; 7 | import MyWorkExperience from "@/components/WorkExperience"; 8 | import AboutMe from "@/components/Aboutme"; 9 | import Blogs_section from "@/components/blogs"; 10 | 11 | const fadeInUp = { 12 | hidden: { opacity: 0, y: 50 }, 13 | visible: { opacity: 1, y: 0, transition: { duration: 0.8 } }, 14 | }; 15 | 16 | export default function Home() { 17 | return ( 18 |
19 | 26 |

Hi, my name is

27 |

28 | Rahul Bhardwaj. 29 |

30 |

31 | I build things for the web. 32 |

33 |

34 | I’m a full-stack developer from India. I specialize in turning ideas 35 | into fully functional web applications. Whether you’re building a 36 | product from the ground up or improving an existing one, I can help 37 | bring your vision to life with clean, efficient code. 38 |

39 | 46 | 51 | 52 | Resume 53 | 54 | 55 | 56 |
57 | 58 | 65 | 66 | 67 | 68 | 75 | 76 | 77 | 78 | 85 | 86 | 87 | {/* 88 | 94 | 95 | 96 | 97 | 104 | 105 | */} 106 | 112 |
113 | © 2024 Rahul Bhardwaj. All rights reserved. 114 | Made with ❤️ by Rahul Bhardwaj 115 |
116 |
117 |
118 | ); 119 | } 120 | -------------------------------------------------------------------------------- /Portfolio/portfolio/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss" 2 | const defaultTheme = require("tailwindcss/defaultTheme"); 3 | const colors = require("tailwindcss/colors"); 4 | const { 5 | default: flattenColorPalette, 6 | } = require("tailwindcss/lib/util/flattenColorPalette"); 7 | 8 | const config = { 9 | darkMode: ["class"], 10 | content: [ 11 | './pages/**/*.{ts,tsx}', 12 | './components/**/*.{ts,tsx}', 13 | './app/**/*.{ts,tsx}', 14 | './src/**/*.{ts,tsx}', 15 | ], 16 | prefix: "", 17 | theme: { 18 | container: { 19 | center: true, 20 | padding: "2rem", 21 | screens: { 22 | "2xl": "1400px", 23 | }, 24 | }, 25 | extend: { 26 | fontFamily: { 27 | montserrat: ['Montserrat', 'sans-serif'], 28 | }, 29 | colors: { 30 | border: "hsl(var(--border))", 31 | input: "hsl(var(--input))", 32 | ring: "hsl(var(--ring))", 33 | background: "hsl(var(--background))", 34 | foreground: "hsl(var(--foreground))", 35 | primary: { 36 | DEFAULT: "hsl(var(--primary))", 37 | foreground: "hsl(var(--primary-foreground))", 38 | }, 39 | secondary: { 40 | DEFAULT: "hsl(var(--secondary))", 41 | foreground: "hsl(var(--secondary-foreground))", 42 | }, 43 | destructive: { 44 | DEFAULT: "hsl(var(--destructive))", 45 | foreground: "hsl(var(--destructive-foreground))", 46 | }, 47 | muted: { 48 | DEFAULT: "hsl(var(--muted))", 49 | foreground: "hsl(var(--muted-foreground))", 50 | }, 51 | accent: { 52 | DEFAULT: "hsl(var(--accent))", 53 | foreground: "hsl(var(--accent-foreground))", 54 | }, 55 | popover: { 56 | DEFAULT: "hsl(var(--popover))", 57 | foreground: "hsl(var(--popover-foreground))", 58 | }, 59 | card: { 60 | DEFAULT: "hsl(var(--card))", 61 | foreground: "hsl(var(--card-foreground))", 62 | }, 63 | }, 64 | borderRadius: { 65 | lg: "var(--radius)", 66 | md: "calc(var(--radius) - 2px)", 67 | sm: "calc(var(--radius) - 4px)", 68 | }, 69 | keyframes: { 70 | "accordion-down": { 71 | from: { height: "0" }, 72 | to: { height: "var(--radix-accordion-content-height)" }, 73 | }, 74 | "accordion-up": { 75 | from: { height: "var(--radix-accordion-content-height)" }, 76 | to: { height: "0" }, 77 | }, 78 | "shine-pulse": { 79 | "0%": { 80 | "background-position": "0% 0%", 81 | }, 82 | "50%": { 83 | "background-position": "100% 100%", 84 | }, 85 | to: { 86 | "background-position": "0% 0%", 87 | }, 88 | }, 89 | "spin-around": { 90 | "0%": { 91 | transform: "translateZ(0) rotate(0)", 92 | }, 93 | "15%, 35%": { 94 | transform: "translateZ(0) rotate(90deg)", 95 | }, 96 | "65%, 85%": { 97 | transform: "translateZ(0) rotate(270deg)", 98 | }, 99 | "100%": { 100 | transform: "translateZ(0) rotate(360deg)", 101 | }, 102 | }, 103 | slide: { 104 | to: { 105 | transform: "translate(calc(100cqw - 100%), 0)", 106 | }, 107 | }, 108 | }, 109 | animation: { 110 | "accordion-down": "accordion-down 0.2s ease-out", 111 | "accordion-up": "accordion-up 0.2s ease-out", 112 | "spin-around": "spin-around calc(var(--speed) * 2) infinite linear", 113 | slide: "slide var(--speed) ease-in-out infinite alternate", 114 | }, 115 | }, 116 | }, 117 | plugins: [ 118 | require("tailwindcss-animate"), 119 | addVariablesForColors, 120 | ], 121 | } satisfies Config 122 | 123 | // This plugin adds each Tailwind color as a global CSS variable, e.g. var(--gray-200). 124 | function addVariablesForColors({ addBase, theme }: any) { 125 | let allColors = flattenColorPalette(theme("colors")); 126 | let newVars = Object.fromEntries( 127 | Object.entries(allColors).map(([key, val]) => [`--${key}`, val]) 128 | ); 129 | addBase({ 130 | ":root": newVars, 131 | }); 132 | } 133 | 134 | export default config -------------------------------------------------------------------------------- /Portfolio/portfolio/components/magicui/particles.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useEffect, useRef, useState } from "react"; 4 | 5 | interface MousePosition { 6 | x: number; 7 | y: number; 8 | } 9 | 10 | function MousePosition(): MousePosition { 11 | const [mousePosition, setMousePosition] = useState({ 12 | x: 0, 13 | y: 0, 14 | }); 15 | 16 | useEffect(() => { 17 | const handleMouseMove = (event: MouseEvent) => { 18 | setMousePosition({ x: event.clientX, y: event.clientY }); 19 | }; 20 | 21 | window.addEventListener("mousemove", handleMouseMove); 22 | 23 | return () => { 24 | window.removeEventListener("mousemove", handleMouseMove); 25 | }; 26 | }, []); 27 | 28 | return mousePosition; 29 | } 30 | 31 | interface ParticlesProps { 32 | className?: string; 33 | quantity?: number; 34 | staticity?: number; 35 | ease?: number; 36 | size?: number; 37 | refresh?: boolean; 38 | color?: string; 39 | vx?: number; 40 | vy?: number; 41 | } 42 | function hexToRgb(hex: string): number[] { 43 | hex = hex.replace("#", ""); 44 | 45 | if (hex.length === 3) { 46 | hex = hex 47 | .split("") 48 | .map((char) => char + char) 49 | .join(""); 50 | } 51 | 52 | const hexInt = parseInt(hex, 16); 53 | const red = (hexInt >> 16) & 255; 54 | const green = (hexInt >> 8) & 255; 55 | const blue = hexInt & 255; 56 | return [red, green, blue]; 57 | } 58 | 59 | const Particles: React.FC = ({ 60 | className = "", 61 | quantity = 100, 62 | staticity = 50, 63 | ease = 50, 64 | size = 0.4, 65 | refresh = false, 66 | color = "#ffffff", 67 | vx = 0, 68 | vy = 0, 69 | }) => { 70 | const canvasRef = useRef(null); 71 | const canvasContainerRef = useRef(null); 72 | const context = useRef(null); 73 | const circles = useRef([]); 74 | const mousePosition = MousePosition(); 75 | const mouse = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); 76 | const canvasSize = useRef<{ w: number; h: number }>({ w: 0, h: 0 }); 77 | const dpr = typeof window !== "undefined" ? window.devicePixelRatio : 1; 78 | 79 | useEffect(() => { 80 | if (canvasRef.current) { 81 | context.current = canvasRef.current.getContext("2d"); 82 | } 83 | initCanvas(); 84 | animate(); 85 | window.addEventListener("resize", initCanvas); 86 | 87 | return () => { 88 | window.removeEventListener("resize", initCanvas); 89 | }; 90 | }, [color]); 91 | 92 | useEffect(() => { 93 | onMouseMove(); 94 | }, [mousePosition.x, mousePosition.y]); 95 | 96 | useEffect(() => { 97 | initCanvas(); 98 | }, [refresh]); 99 | 100 | const initCanvas = () => { 101 | resizeCanvas(); 102 | drawParticles(); 103 | }; 104 | 105 | const onMouseMove = () => { 106 | if (canvasRef.current) { 107 | const rect = canvasRef.current.getBoundingClientRect(); 108 | const { w, h } = canvasSize.current; 109 | const x = mousePosition.x - rect.left - w / 2; 110 | const y = mousePosition.y - rect.top - h / 2; 111 | const inside = x < w / 2 && x > -w / 2 && y < h / 2 && y > -h / 2; 112 | if (inside) { 113 | mouse.current.x = x; 114 | mouse.current.y = y; 115 | } 116 | } 117 | }; 118 | 119 | type Circle = { 120 | x: number; 121 | y: number; 122 | translateX: number; 123 | translateY: number; 124 | size: number; 125 | alpha: number; 126 | targetAlpha: number; 127 | dx: number; 128 | dy: number; 129 | magnetism: number; 130 | }; 131 | 132 | const resizeCanvas = () => { 133 | if (canvasContainerRef.current && canvasRef.current && context.current) { 134 | circles.current.length = 0; 135 | canvasSize.current.w = canvasContainerRef.current.offsetWidth; 136 | canvasSize.current.h = canvasContainerRef.current.offsetHeight; 137 | canvasRef.current.width = canvasSize.current.w * dpr; 138 | canvasRef.current.height = canvasSize.current.h * dpr; 139 | canvasRef.current.style.width = `${canvasSize.current.w}px`; 140 | canvasRef.current.style.height = `${canvasSize.current.h}px`; 141 | context.current.scale(dpr, dpr); 142 | } 143 | }; 144 | 145 | const circleParams = (): Circle => { 146 | const x = Math.floor(Math.random() * canvasSize.current.w); 147 | const y = Math.floor(Math.random() * canvasSize.current.h); 148 | const translateX = 0; 149 | const translateY = 0; 150 | const pSize = Math.floor(Math.random() * 2) + size; 151 | const alpha = 0; 152 | const targetAlpha = parseFloat((Math.random() * 0.6 + 0.1).toFixed(1)); 153 | const dx = (Math.random() - 0.5) * 0.1; 154 | const dy = (Math.random() - 0.5) * 0.1; 155 | const magnetism = 0.1 + Math.random() * 4; 156 | return { 157 | x, 158 | y, 159 | translateX, 160 | translateY, 161 | size: pSize, 162 | alpha, 163 | targetAlpha, 164 | dx, 165 | dy, 166 | magnetism, 167 | }; 168 | }; 169 | 170 | const rgb = hexToRgb(color); 171 | 172 | const drawCircle = (circle: Circle, update = false) => { 173 | if (context.current) { 174 | const { x, y, translateX, translateY, size, alpha } = circle; 175 | context.current.translate(translateX, translateY); 176 | context.current.beginPath(); 177 | context.current.arc(x, y, size, 0, 2 * Math.PI); 178 | context.current.fillStyle = `rgba(${rgb.join(", ")}, ${alpha})`; 179 | context.current.fill(); 180 | context.current.setTransform(dpr, 0, 0, dpr, 0, 0); 181 | 182 | if (!update) { 183 | circles.current.push(circle); 184 | } 185 | } 186 | }; 187 | 188 | const clearContext = () => { 189 | if (context.current) { 190 | context.current.clearRect( 191 | 0, 192 | 0, 193 | canvasSize.current.w, 194 | canvasSize.current.h, 195 | ); 196 | } 197 | }; 198 | 199 | const drawParticles = () => { 200 | clearContext(); 201 | const particleCount = quantity; 202 | for (let i = 0; i < particleCount; i++) { 203 | const circle = circleParams(); 204 | drawCircle(circle); 205 | } 206 | }; 207 | 208 | const remapValue = ( 209 | value: number, 210 | start1: number, 211 | end1: number, 212 | start2: number, 213 | end2: number, 214 | ): number => { 215 | const remapped = 216 | ((value - start1) * (end2 - start2)) / (end1 - start1) + start2; 217 | return remapped > 0 ? remapped : 0; 218 | }; 219 | 220 | const animate = () => { 221 | clearContext(); 222 | circles.current.forEach((circle: Circle, i: number) => { 223 | // Handle the alpha value 224 | const edge = [ 225 | circle.x + circle.translateX - circle.size, // distance from left edge 226 | canvasSize.current.w - circle.x - circle.translateX - circle.size, // distance from right edge 227 | circle.y + circle.translateY - circle.size, // distance from top edge 228 | canvasSize.current.h - circle.y - circle.translateY - circle.size, // distance from bottom edge 229 | ]; 230 | const closestEdge = edge.reduce((a, b) => Math.min(a, b)); 231 | const remapClosestEdge = parseFloat( 232 | remapValue(closestEdge, 0, 20, 0, 1).toFixed(2), 233 | ); 234 | if (remapClosestEdge > 1) { 235 | circle.alpha += 0.02; 236 | if (circle.alpha > circle.targetAlpha) { 237 | circle.alpha = circle.targetAlpha; 238 | } 239 | } else { 240 | circle.alpha = circle.targetAlpha * remapClosestEdge; 241 | } 242 | circle.x += circle.dx + vx; 243 | circle.y += circle.dy + vy; 244 | circle.translateX += 245 | (mouse.current.x / (staticity / circle.magnetism) - circle.translateX) / 246 | ease; 247 | circle.translateY += 248 | (mouse.current.y / (staticity / circle.magnetism) - circle.translateY) / 249 | ease; 250 | 251 | drawCircle(circle, true); 252 | 253 | // circle gets out of the canvas 254 | if ( 255 | circle.x < -circle.size || 256 | circle.x > canvasSize.current.w + circle.size || 257 | circle.y < -circle.size || 258 | circle.y > canvasSize.current.h + circle.size 259 | ) { 260 | // remove the circle from the array 261 | circles.current.splice(i, 1); 262 | // create a new circle 263 | const newCircle = circleParams(); 264 | drawCircle(newCircle); 265 | // update the circle position 266 | } 267 | }); 268 | window.requestAnimationFrame(animate); 269 | }; 270 | 271 | return ( 272 | 275 | ); 276 | }; 277 | 278 | export default Particles; 279 | -------------------------------------------------------------------------------- /Portfolio/portfolio/components/ui/canvas-reveal-effect.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { cn } from "@/lib/utils"; 3 | import { Canvas, useFrame, useThree } from "@react-three/fiber"; 4 | import React, { useMemo, useRef } from "react"; 5 | import * as THREE from "three"; 6 | 7 | export const CanvasRevealEffect = ({ 8 | animationSpeed = 0.4, 9 | opacities = [0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.8, 0.8, 0.8, 1], 10 | colors = [[0, 255, 255]], 11 | containerClassName, 12 | dotSize, 13 | showGradient = true, 14 | }: { 15 | /** 16 | * 0.1 - slower 17 | * 1.0 - faster 18 | */ 19 | animationSpeed?: number; 20 | opacities?: number[]; 21 | colors?: number[][]; 22 | containerClassName?: string; 23 | dotSize?: number; 24 | showGradient?: boolean; 25 | }) => { 26 | return ( 27 |
28 |
29 | 43 |
44 | {showGradient && ( 45 |
46 | )} 47 |
48 | ); 49 | }; 50 | 51 | interface DotMatrixProps { 52 | colors?: number[][]; 53 | opacities?: number[]; 54 | totalSize?: number; 55 | dotSize?: number; 56 | shader?: string; 57 | center?: ("x" | "y")[]; 58 | } 59 | 60 | const DotMatrix: React.FC = ({ 61 | colors = [[0, 0, 0]], 62 | opacities = [0.04, 0.04, 0.04, 0.04, 0.04, 0.08, 0.08, 0.08, 0.08, 0.14], 63 | totalSize = 4, 64 | dotSize = 2, 65 | shader = "", 66 | center = ["x", "y"], 67 | }) => { 68 | const uniforms = React.useMemo(() => { 69 | let colorsArray = [ 70 | colors[0], 71 | colors[0], 72 | colors[0], 73 | colors[0], 74 | colors[0], 75 | colors[0], 76 | ]; 77 | if (colors.length === 2) { 78 | colorsArray = [ 79 | colors[0], 80 | colors[0], 81 | colors[0], 82 | colors[1], 83 | colors[1], 84 | colors[1], 85 | ]; 86 | } else if (colors.length === 3) { 87 | colorsArray = [ 88 | colors[0], 89 | colors[0], 90 | colors[1], 91 | colors[1], 92 | colors[2], 93 | colors[2], 94 | ]; 95 | } 96 | 97 | return { 98 | u_colors: { 99 | value: colorsArray.map((color) => [ 100 | color[0] / 255, 101 | color[1] / 255, 102 | color[2] / 255, 103 | ]), 104 | type: "uniform3fv", 105 | }, 106 | u_opacities: { 107 | value: opacities, 108 | type: "uniform1fv", 109 | }, 110 | u_total_size: { 111 | value: totalSize, 112 | type: "uniform1f", 113 | }, 114 | u_dot_size: { 115 | value: dotSize, 116 | type: "uniform1f", 117 | }, 118 | }; 119 | }, [colors, opacities, totalSize, dotSize]); 120 | 121 | return ( 122 | 175 | ); 176 | }; 177 | 178 | type Uniforms = { 179 | [key: string]: { 180 | value: number[] | number[][] | number; 181 | type: string; 182 | }; 183 | }; 184 | const ShaderMaterial = ({ 185 | source, 186 | uniforms, 187 | maxFps = 60, 188 | }: { 189 | source: string; 190 | hovered?: boolean; 191 | maxFps?: number; 192 | uniforms: Uniforms; 193 | }) => { 194 | const { size } = useThree(); 195 | const ref = useRef(); 196 | let lastFrameTime = 0; 197 | 198 | useFrame(({ clock }) => { 199 | if (!ref.current) return; 200 | const timestamp = clock.getElapsedTime(); 201 | if (timestamp - lastFrameTime < 1 / maxFps) { 202 | return; 203 | } 204 | lastFrameTime = timestamp; 205 | 206 | const material: any = ref.current.material; 207 | const timeLocation = material.uniforms.u_time; 208 | timeLocation.value = timestamp; 209 | }); 210 | 211 | const getUniforms = () => { 212 | const preparedUniforms: any = {}; 213 | 214 | for (const uniformName in uniforms) { 215 | const uniform: any = uniforms[uniformName]; 216 | 217 | switch (uniform.type) { 218 | case "uniform1f": 219 | preparedUniforms[uniformName] = { value: uniform.value, type: "1f" }; 220 | break; 221 | case "uniform3f": 222 | preparedUniforms[uniformName] = { 223 | value: new THREE.Vector3().fromArray(uniform.value), 224 | type: "3f", 225 | }; 226 | break; 227 | case "uniform1fv": 228 | preparedUniforms[uniformName] = { value: uniform.value, type: "1fv" }; 229 | break; 230 | case "uniform3fv": 231 | preparedUniforms[uniformName] = { 232 | value: uniform.value.map((v: number[]) => 233 | new THREE.Vector3().fromArray(v) 234 | ), 235 | type: "3fv", 236 | }; 237 | break; 238 | case "uniform2f": 239 | preparedUniforms[uniformName] = { 240 | value: new THREE.Vector2().fromArray(uniform.value), 241 | type: "2f", 242 | }; 243 | break; 244 | default: 245 | console.error(`Invalid uniform type for '${uniformName}'.`); 246 | break; 247 | } 248 | } 249 | 250 | preparedUniforms["u_time"] = { value: 0, type: "1f" }; 251 | preparedUniforms["u_resolution"] = { 252 | value: new THREE.Vector2(size.width * 2, size.height * 2), 253 | }; // Initialize u_resolution 254 | return preparedUniforms; 255 | }; 256 | 257 | // Shader material 258 | const material = useMemo(() => { 259 | const materialObject = new THREE.ShaderMaterial({ 260 | vertexShader: ` 261 | precision mediump float; 262 | in vec2 coordinates; 263 | uniform vec2 u_resolution; 264 | out vec2 fragCoord; 265 | void main(){ 266 | float x = position.x; 267 | float y = position.y; 268 | gl_Position = vec4(x, y, 0.0, 1.0); 269 | fragCoord = (position.xy + vec2(1.0)) * 0.5 * u_resolution; 270 | fragCoord.y = u_resolution.y - fragCoord.y; 271 | } 272 | `, 273 | fragmentShader: source, 274 | uniforms: getUniforms(), 275 | glslVersion: THREE.GLSL3, 276 | blending: THREE.CustomBlending, 277 | blendSrc: THREE.SrcAlphaFactor, 278 | blendDst: THREE.OneFactor, 279 | }); 280 | 281 | return materialObject; 282 | }, [size.width, size.height, source]); 283 | 284 | return ( 285 | 286 | 287 | 288 | 289 | ); 290 | }; 291 | 292 | const Shader: React.FC = ({ source, uniforms, maxFps = 60 }) => { 293 | return ( 294 | 295 | 296 | 297 | ); 298 | }; 299 | interface ShaderProps { 300 | source: string; 301 | uniforms: { 302 | [key: string]: { 303 | value: number[] | number[][] | number; 304 | type: string; 305 | }; 306 | }; 307 | maxFps?: number; 308 | } 309 | --------------------------------------------------------------------------------