Repository: avneesh0612/portfolio
Branch: main
Commit: deb869ce7585
Files: 46
Total size: 46.1 KB
Directory structure:
gitextract_38gvouyj/
├── .gitignore
├── LICENSE
├── README.md
├── eslint.config.mjs
├── next.config.ts
├── package.json
├── postcss.config.mjs
├── public/
│ ├── fonts/
│ │ ├── Geomanist-Regular-Italic.otf
│ │ └── Geomanist-Regular.otf
│ ├── robots.txt
│ ├── rss.xml
│ └── sitemap.xml
├── src/
│ ├── app/
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components/
│ │ ├── Blog.tsx
│ │ ├── Contact.tsx
│ │ ├── Footer.tsx
│ │ ├── Header.tsx
│ │ ├── Hero.tsx
│ │ ├── Icons/
│ │ │ ├── CrossIcon.tsx
│ │ │ ├── FarcasterIcon.tsx
│ │ │ ├── GithubIcon.tsx
│ │ │ ├── LinkedInIcon.tsx
│ │ │ ├── Logo.tsx
│ │ │ ├── MailIcon.tsx
│ │ │ ├── MenuIcon.tsx
│ │ │ ├── VisitIcon.tsx
│ │ │ ├── XIcon.tsx
│ │ │ └── index.ts
│ │ ├── Main.tsx
│ │ ├── Projects.tsx
│ │ ├── Work.tsx
│ │ ├── index.ts
│ │ ├── theme-provider.tsx
│ │ └── theme-toggle.tsx
│ ├── data/
│ │ ├── index.ts
│ │ ├── nav.ts
│ │ ├── personal.ts
│ │ ├── projects.ts
│ │ ├── social.tsx
│ │ └── work.ts
│ ├── types/
│ │ └── PostType.ts
│ └── utils/
│ └── getPosts.ts
├── tailwind.config.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 Avneesh Agarwal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<h1 align="center">Portfolio</h1>
<p>
<a href="https://github.com/avneesh0612/portfolio/blob/main/LICENSE" target="_blank">
<img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" />
</a>
<a href="https://X.com/avneesh0612" target="_blank">
<img alt="X: avneesh0612" src="https://img.shields.io/twitter/follow/avneesh0612.svg?style=social" />
</a>
</p>
A minimalistic SEO-friendly portfolio template built with Next.js and Tailwind CSS. Feel Free to fork it, update your details, and use it.

## Links
- [Live Demo](https://www.avneesh.tech/)
- [Source Code](https://github.com/avneesh0612/portfolio)
## Developer
**Avneesh Agarwal**
- Website: [avneesh.tech](https://www.avneesh.tech/)
- GitHub: [@avneesh0612](https://github.com/avneesh0612)
- X: [@avneesh0612](https://X.com/avneesh0612)
- LinkedIn: [@avneesh0612](https://linkedin.com/in/avneesh0612)
- Warpcast: [@avneesh0612](https://warpcast.com/avneesh)
## License
[MIT](https://github.com/avneesh0612/portfolio/blob/main/LICENSE) © 2025 Avneesh Agarwal
================================================
FILE: eslint.config.mjs
================================================
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
];
export default eslintConfig;
================================================
FILE: next.config.ts
================================================
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;
================================================
FILE: package.json
================================================
{
"name": "portfolio",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"framer-motion": "^12.5.0",
"lucide-react": "^0.483.0",
"next": "15.2.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-rough-notation": "^1.0.5",
"react-scroll": "^1.9.3",
"schema-dts": "^1.1.5"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.0",
"@tailwindcss/postcss": "^4.0.14",
"@types/node": "^20.17.24",
"@types/react": "^19.0.11",
"@types/react-dom": "^19.0.4",
"@types/react-scroll": "^1.8.10",
"eslint": "^9.22.0",
"eslint-config-next": "15.2.3",
"tailwindcss": "^4.0.14",
"typescript": "^5.8.2"
}
}
================================================
FILE: postcss.config.mjs
================================================
const config = {
plugins: ["@tailwindcss/postcss"],
};
export default config;
================================================
FILE: public/robots.txt
================================================
User-agent: *
Disallow:
================================================
FILE: public/rss.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Avneesh Agarwal</title>
<link>https://avneesh.tech/</link>
<description>Hey, I'm Avneesh Agarwal — a developer based in India, passionate about
building powerful dev tools, contributing to open source, and sharing my learnings
through writing. Currently, I'm the CTO at Orcas, where we're reshaping equity
crowdfunding for startups. I've worked across multiple startups as a developer relations
engineer, full-stack developer, and technical writer, helping teams build, scale, and
engage with developer communities. When I'm not coding, you'll find me experimenting
with side projects, writing articles, or diving into something completely random—just
for the fun of it. Oh, and I'm also a sports enthusiast (fitness freak + nerd combo :p).</description>
<lastBuildDate>Thurs, 20 Mar 2025 12:00:00 GMT</lastBuildDate>
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
<generator>https://github.com/jpmonette/feed</generator>
<language>en</language>
<image>
<title>Avneesh Agarwal</title>
<url>https://avneesh.tech/about.png</url>
<link>https://avneesh.tech/</link>
</image>
<copyright>All rights reserved, Avneesh Agarwal</copyright>
<category>Technology</category>
<category>Programming</category>
<category>Web Development</category>
<category>Web3 development</category>
<category>Blogger</category>
<category>Avneesh Agarwal</category>
</channel>
</rss>
================================================
FILE: public/sitemap.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://avneesh.tech/</loc>
<lastmod>2025-03-20</lastmod>
<priority>1.0</priority>
</url>
</urlset>
================================================
FILE: src/app/globals.css
================================================
@import "tailwindcss";
@config "../../tailwind.config.ts";
:root {
--background: theme("colors.background.light");
--foreground: theme("colors.foreground.light");
--icon-color: theme("colors.neutral.900");
--primary: theme("colors.primary.DEFAULT");
--primary-hover: theme("colors.primary.hover");
--accent-first: theme("colors.accent.first");
--accent-second: theme("colors.accent.second");
--accent-third: theme("colors.accent.third");
}
:root.dark {
--background: theme("colors.background.dark");
--foreground: theme("colors.foreground.dark");
--icon-color: theme("colors.neutral.100");
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
body {
background: var(--background);
color: var(--foreground);
transition: background-color 0.3s ease, color 0.3s ease;
}
@font-face {
font-family: "Geomanist";
src: url("/fonts/Geomanist-Regular.otf") format("opentype");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Geomanist";
src: url("/fonts/Geomanist-Regular-Italic.otf") format("opentype");
font-weight: 400;
font-style: italic;
font-display: swap;
}
================================================
FILE: src/app/layout.tsx
================================================
import { Footer, Header } from "@/components";
import { ThemeProvider } from "@/components/theme-provider";
import { personalData } from "@/data";
import type { Metadata, Viewport } from "next";
import "./globals.css";
export const viewport: Viewport = {
themeColor: "#0A0A0A",
width: "device-width",
initialScale: 1,
maximumScale: 5,
};
export const metadata: Metadata = {
metadataBase: new URL(personalData.site),
title: {
template: `%s | ${personalData.name}`,
default: `${personalData.name} | ${personalData.designation}`,
},
description: personalData.metaDescription,
authors: [{ name: personalData.name, url: personalData.site }],
keywords: personalData.keywords,
referrer: "no-referrer-when-downgrade",
alternates: {
canonical: personalData.site,
languages: {
"en-US": personalData.site,
},
},
openGraph: {
title: `${personalData.name} | ${personalData.designation}`,
description: personalData.metaDescription,
url: personalData.site,
siteName: personalData.name,
images: [
{
url: "/about.png",
width: 1200,
height: 630,
alt: `${personalData.name} - ${personalData.designation}`,
},
],
type: "website",
locale: "en-US",
},
twitter: {
card: "summary_large_image",
title: `${personalData.name} | ${personalData.designation}`,
description: personalData.metaDescription,
creator: `@${personalData.x}`,
images: ["/about.png"],
},
icons: {
icon: "/favicon.ico",
apple: "/apple-touch-icon.png",
shortcut: "/favicon.ico",
},
manifest: "/site.webmanifest",
robots: {
index: true,
follow: true,
nocache: true,
googleBot: {
index: true,
follow: true,
nocache: true,
"max-snippet": -1,
"max-image-preview": "large",
"max-video-preview": -1,
},
},
category: "website",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body className="antialiased font-geomanist">
<ThemeProvider>
<Header />
{children}
<Footer />
</ThemeProvider>
</body>
</html>
);
}
================================================
FILE: src/app/page.tsx
================================================
import { Hero, Main } from "@/components";
import { personalData, socialLinks } from "@/data";
import getUserDataAndPosts from "@/utils/getPosts";
import { WebSite, WithContext } from "schema-dts";
async function getPosts() {
const Posts = await getUserDataAndPosts("avneesh0612");
return Posts;
}
const jsonLd: WithContext<WebSite> = {
"@context": "https://schema.org",
"@type": "WebSite",
name: personalData.name,
url: personalData.site,
description: personalData.shorterDesc,
image: `${personalData.site}/about.png`,
author: {
"@type": "Person",
name: personalData.name,
url: personalData.site,
},
sameAs: socialLinks.map((link) => link.link),
potentialAction: {
"@type": "SearchAction",
target: `${personalData.site}/search?q={search_term_string}`,
},
mainEntityOfPage: {
"@type": "WebPage",
"@id": personalData.site,
},
};
export default async function Home() {
const posts = await getPosts();
return (
<div className="flex flex-col px-0 pt-8 md:px-8 lg:px-18">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<Hero />
<Main posts={posts} />
</div>
);
}
================================================
FILE: src/components/Blog.tsx
================================================
import { personalData } from "@/data";
import { PostType } from "@/types/PostType";
import type { FC } from "react";
interface PostsType {
posts: PostType[];
}
export const Blog: FC<PostsType> = ({ posts }) => {
return (
<section className="py-12 px-4" id="blog" aria-labelledby="blog-heading">
<h2 id="blog-heading" className="text-4xl font-light text-center mb-8">
Latest Blog Posts
</h2>
<div className="max-w-4xl mx-auto space-y-8 md:space-y-8 px-4 md:px-0 pt-6">
{posts.map((post) => (
<article
key={post.data.post.slug}
className="block border-l-4 border-neutral-700 pl-4 md:pl-4 hover:border-neutral-900 dark:hover:border-neutral-300 transition-all duration-200"
>
<a
href={`${personalData.blog}/${post.data.post.slug}`}
className="block pb-6 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 dark:focus:ring-offset-background-dark rounded-md p-2"
aria-label={`Read ${post.data.post.title}`}
target="_blank"
rel="noopener noreferrer"
>
<h3 className="text-2xl font-medium text-neutral-900 group-hover:text-neutral-600 dark:text-neutral-100 dark:group-hover:text-neutral-300 transition-colors">
{post.data.post.title}
<span className="text-lg text-neutral-400 ml-2">
({post.data.post.readTimeInMinutes} min read)
</span>
</h3>
<p className="text-neutral-500 text-sm mt-3 line-clamp-2">
{post.data.post.brief}
</p>
<div className="text-neutral-400 text-sm mt-3 flex items-center gap-4">
<span
className="flex items-center gap-1"
title="Reactions"
aria-label={`${post.data.post.reactionCount} reactions`}
>
<span aria-hidden="true">❤️</span>
{post.data.post.reactionCount}
</span>
<span
className="flex items-center gap-1"
title="Comments"
aria-label={`${
post.data.post.replyCount + post.data.post.responseCount
} comments`}
>
<span aria-hidden="true">💬</span>
{post.data.post.replyCount + post.data.post.responseCount}
</span>
</div>
</a>
</article>
))}
</div>
</section>
);
};
================================================
FILE: src/components/Contact.tsx
================================================
import { socialLinks } from "@/data";
import type { FC } from "react";
export const Contact: FC = () => {
return (
<section
className="py-8 sm:py-12"
id="contact"
aria-labelledby="contact-heading"
>
<h2
id="contact-heading"
className="text-4xl sm:text-4xl font-light text-center mb-8 sm:mb-8 px-4"
>
Get in Touch
</h2>
<div
className="flex justify-center flex-wrap gap-2 sm:gap-4 px-4 mb-6 sm:mb-8"
role="list"
aria-label="Social media links"
>
{socialLinks.map(({ link, Icon, name }, index) => (
<a
key={index}
href={link}
target="_blank"
rel="noopener noreferrer"
className="hover:opacity-80 transition focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 dark:focus:ring-offset-background-dark p-2 rounded-md"
aria-label={`Connect on ${name}`}
title={`Connect on ${name}`}
role="listitem"
>
<Icon className="w-6 h-6 sm:w-8 sm:h-8 text-neutral-900 dark:text-neutral-100" />
</a>
))}
</div>
</section>
);
};
================================================
FILE: src/components/Footer.tsx
================================================
import { personalData } from "@/data";
import type { FC } from "react";
export const Footer: FC = () => {
const currentYear = new Date().getFullYear();
return (
<footer
className="w-full bg-neutral-100 dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100 text-center shadow-sm mx-auto"
role="contentinfo"
aria-label="Site footer"
>
<p className="text-neutral-600 dark:text-neutral-400 text-sm py-4">
© {currentYear} {personalData.name}. All rights reserved.
</p>
</footer>
);
};
================================================
FILE: src/components/Header.tsx
================================================
"use client";
import { navLinks } from "@/data";
import { AnimatePresence, motion } from "framer-motion";
import { MenuIcon, X } from "lucide-react";
import { FC, useState } from "react";
import { Link } from "react-scroll";
import Logo from "./Icons/Logo";
import { ThemeToggle } from "./theme-toggle";
export const Header: FC = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<header className="w-full py-4 px-4 sm:px-16 bg-background-light/70 dark:bg-background-dark/70 backdrop-blur-md fixed top-0 z-50 flex justify-between items-center box-border">
<Link
href="/"
className="text-2xl font-bold text-neutral-900 hover:text-neutral-600 dark:text-neutral-100 dark:hover:text-neutral-400 transition"
to="home"
>
<Logo width={60} height={40} />
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className="text-neutral-900 hover:text-neutral-600 dark:text-neutral-100 dark:hover:text-neutral-400 transition"
to={link.href.replace("#", "")}
spy={true}
smooth={true}
offset={-70}
duration={500}
onClick={() => setIsMenuOpen(false)}
onSetActive={() => setIsMenuOpen(false)}
onSetInactive={() => setIsMenuOpen(false)}
>
{link.label}
</Link>
))}
<ThemeToggle />
</nav>
{/* Mobile Navigation Button */}
<div className="md:hidden flex items-center space-x-4">
<ThemeToggle />
<motion.button
className="focus:outline-none"
onClick={() => setIsMenuOpen(!isMenuOpen)}
aria-label="Toggle menu"
aria-expanded={isMenuOpen}
whileTap={{ scale: 0.95 }}
>
{isMenuOpen ? (
<X className="w-6 h-6 text-neutral-900 dark:text-neutral-100" />
) : (
<MenuIcon className="w-6 h-6 text-neutral-900 dark:text-neutral-100" />
)}
</motion.button>
</div>
{/* Mobile Navigation Menu */}
<AnimatePresence>
{isMenuOpen && (
<motion.nav
className="md:hidden absolute top-16 left-0 right-0 bg-background-light dark:bg-background-dark p-4"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.2 }}
>
{navLinks.map((link, index) => (
<motion.div
key={link.href}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1 }}
>
<Link
href={link.href}
className="block py-2 text-neutral-900 hover:text-neutral-600 dark:text-neutral-400 dark:hover:text-neutral-200 transition"
onClick={() => setIsMenuOpen(false)}
to={link.href.replace("#", "")}
spy={true}
smooth={true}
offset={-70}
duration={500}
onSetActive={() => setIsMenuOpen(false)}
onSetInactive={() => setIsMenuOpen(false)}
>
{link.label}
</Link>
</motion.div>
))}
</motion.nav>
)}
</AnimatePresence>
</header>
);
};
================================================
FILE: src/components/Hero.tsx
================================================
import { personalData } from "@/data";
import Image from "next/image";
import type { FC } from "react";
import { RoughNotation, RoughNotationGroup } from "react-rough-notation";
import { Download } from "lucide-react";
export const Hero: FC = () => {
return (
<section
className="flex w-full flex-col-reverse md:flex-row items-center justify-between pt-4 md:pt-0 gap-4 md:min-h-screen px-2 md:px-0"
id="home"
>
<div className="flex flex-col px-4 md:px-0">
<RoughNotationGroup show>
<div>
<h1 className="text-3xl md:text-4xl lg:text-5xl font-bold text-neutral-900 dark:text-neutral-100">
Hey, I'm{" "}
<RoughNotation
type="highlight"
color="var(--accent-first)"
order="1"
multiline
>
{personalData.name}
</RoughNotation>
</h1>
<p className="text-lg md:text-xl lg:text-2xl font-light leading-relaxed text-neutral-900 dark:text-neutral-100 md:flex-2/3">
— a high school student and developer based in India, passionate
about building powerful dev tools, contributing to open source,
and sharing my learnings through writing. Currently, I'm the{" "}
<RoughNotation
type="underline"
color="var(--accent-second)"
order="2"
multiline
>
CTO at Orcas
</RoughNotation>
, where we're reshaping equity crowdfunding for startups.
I've worked across multiple startups as a{" "}
<RoughNotation
type="highlight"
color="var(--primary)"
order="3"
multiline
>
developer relations engineer, full-stack developer, and
technical writer
</RoughNotation>
, helping teams build, scale, and engage with developer
communities. When I'm not coding, you'll find me
experimenting with side projects, writing articles, or diving into
something completely random—just for the fun of it. Oh, and
I'm also a sports enthusiast{" "}
<RoughNotation
type="bracket"
color="var(--accent-third)"
order="5"
brackets={["left", "right"]}
multiline
>
fitness freak + nerd :p.
</RoughNotation>{" "}
Got a startup that needs someone like me?{" "}
<RoughNotation
type="underline"
color="var(--primary)"
order="6"
iterations={6}
multiline
>
<a
href={`mailto:${personalData.email}`}
className="text-primary hover:text-primary-hover dark:text-primary/90 dark:hover:text-primary-hover/90"
>
Let's talk!
</a>
</RoughNotation>
</p>
</div>
</RoughNotationGroup>
<div className="mt-8 flex items-center gap-4">
<a
href="/CV.pdf"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-4 py-2 rounded-md border border-neutral-300 dark:border-neutral-700 text-neutral-900 dark:text-neutral-100 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-neutral-300 focus:ring-offset-2 dark:focus:ring-offset-background-dark"
aria-label="Download my CV"
>
<Download className="h-4 w-4" />
Download CV
</a>
</div>
</div>
<Image
src="/pfp.png"
alt={personalData.name}
width={300}
height={300}
className="size-[90%] md:size-[300px] mb-4 p-4 md:p-10 md:m-10 border-2 border-neutral-200 dark:border-neutral-200/20 shadow-lg shadow-neutral-200/50 dark:shadow-neutral-200/10 hover:shadow-neutral-300/50 dark:hover:shadow-neutral-200/20 transition-all duration-200 mt-10 md:mt-0"
priority
/>
</section>
);
};
================================================
FILE: src/components/Icons/CrossIcon.tsx
================================================
import React from "react";
export const CrossIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
fill="var(--icon-color)"
width="24"
height="24"
version="1.1"
id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox="0 0 490 490"
xmlSpace="preserve"
{...props}
>
<polygon
points="456.851,0 245,212.564 33.149,0 0.708,32.337 212.669,245.004 0.708,457.678 33.149,490 245,277.443 456.851,490
489.292,457.678 277.331,245.004 489.292,32.337 "
/>
</svg>
);
================================================
FILE: src/components/Icons/FarcasterIcon.tsx
================================================
import React from "react";
export const FarcasterIcon: React.FC<React.SVGProps<SVGSVGElement>> = (
props
) => (
<svg
viewBox="0 0 752 690"
fill="var(--icon-color)"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M129.778 0.556H614.222V689.444H543.111V373.889H542.414C534.554 286.677 461.258 218.333 372 218.333C282.742 218.333 209.446 286.677 201.586 373.889H200.889V689.444H129.778V0.556Z"
fill="var(--icon-color)"
/>
<path
d="M0.888672 98.333L29.7777 196.111H54.2217V591.667C41.9487 591.667 31.9997 601.616 31.9997 613.889V640.556H27.5557C15.2827 640.556 5.33266 650.505 5.33266 662.778V689.444H254.222V662.778C254.222 650.505 244.273 640.556 232 640.556H227.556V613.889C227.556 601.616 217.606 591.667 205.333 591.667H178.667V98.333H0.888672Z"
fill="var(--icon-color)"
/>
<path
d="M547.556 591.667C535.283 591.667 525.333 601.616 525.333 613.889V640.556H520.889C508.616 640.556 498.667 650.505 498.667 662.778V689.444H747.556V662.778C747.556 650.505 737.606 640.556 725.333 640.556H720.889V613.889C720.889 601.616 710.94 591.667 698.667 591.667V196.111H723.111L752 98.333H574.222V591.667H547.556Z"
fill="var(--icon-color)"
/>
</svg>
);
================================================
FILE: src/components/Icons/GithubIcon.tsx
================================================
import React from "react";
export const GithubIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
{...props}
viewBox="0 0 24 24"
>
<g clipPath="url(#prefix__clip0)">
<path
stroke="var(--icon-color)"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M16 22v-3.87a3.37 3.37 0 00-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0020 4.77 5.07 5.07 0 0019.91 1S18.73.65 16 2.48a13.38 13.38 0 00-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 005 4.77a5.44 5.44 0 00-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 009 18.13V22m0-3c-5 1.5-5-2.5-7-3l7 3z"
/>
</g>
<defs>
<clipPath id="prefix__clip0">
<path fill="#fff" d="M0 0h24v24H0z" />
</clipPath>
</defs>
</svg>
);
================================================
FILE: src/components/Icons/LinkedInIcon.tsx
================================================
import React from "react";
export const LinkedInIcon: React.FC<React.SVGProps<SVGSVGElement>> = (
props
) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
{...props}
>
<path
stroke="var(--icon-color)"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M16 8a6 6 0 016 6v7h-4v-7a2 2 0 00-4 0v7h-4v-7a6 6 0 016-6v0zM6 9H2v12h4V9zM4 6a2 2 0 100-4 2 2 0 000 4z"
/>
</svg>
);
================================================
FILE: src/components/Icons/Logo.tsx
================================================
import React from "react";
const Logo: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
width="24"
height="24"
viewBox="0 0 460 269"
fill="var(--icon-color)"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0 269L459.239 55.6309L210.543 145.063L134.239 0L0 269ZM200.652 230.27V237.312H254.348L240.217 209.144L200.652 230.27ZM130 87.3194L90.4347 183.089L163.913 153.513L130 87.3194Z"
fill="var(--icon-color)"
/>
</svg>
);
export default Logo;
================================================
FILE: src/components/Icons/MailIcon.tsx
================================================
import React from "react";
export const MailIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
{...props}
viewBox="0 0 24 24"
>
<path
stroke="var(--icon-color)"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"
/>
<path
stroke="var(--icon-color)"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M22 6l-10 7L2 6"
/>
</svg>
);
================================================
FILE: src/components/Icons/MenuIcon.tsx
================================================
import React from "react";
export const MenuIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M4 18L20 18"
stroke="var(--icon-color)"
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="M4 12L20 12"
stroke="var(--icon-color)"
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="M4 6L20 6"
stroke="var(--icon-color)"
strokeWidth="2"
strokeLinecap="round"
/>
</svg>
);
================================================
FILE: src/components/Icons/VisitIcon.tsx
================================================
import React from "react";
export const VisitIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
className="icon"
stroke="var(--icon-color)"
fill="none"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M18 13V19C18 19.5304 17.7893 20.0391 17.4142 20.4142C17.0391 20.7893 16.5304 21 16 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V8C3 7.46957 3.21071 6.96086 3.58579 6.58579C3.96086 6.21071 4.46957 6 5 6H11"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
<path
d="M15 3H21V9"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
<path
d="M10 14L21 3"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
);
================================================
FILE: src/components/Icons/XIcon.tsx
================================================
import React from "react";
export const XIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 50 50"
width="24"
height="24"
{...props}
>
<path
fill="var(--icon-color)"
d="M 5.9199219 6 L 20.582031 27.375 L 6.2304688 44 L 9.4101562 44 L 21.986328 29.421875 L 31.986328 44 L 44 44 L 28.681641 21.669922 L 42.199219 6 L 39.029297 6 L 27.275391 19.617188 L 17.933594 6 L 5.9199219 6 z M 9.7167969 8 L 16.880859 8 L 40.203125 42 L 33.039062 42 L 9.7167969 8 z"
/>
</svg>
);
================================================
FILE: src/components/Icons/index.ts
================================================
export { GithubIcon } from "./GithubIcon";
export { VisitIcon } from "./VisitIcon";
export { MailIcon } from "./MailIcon";
export { FarcasterIcon } from "./FarcasterIcon";
export { XIcon } from "./XIcon";
export { LinkedInIcon } from "./LinkedInIcon";
================================================
FILE: src/components/Main.tsx
================================================
"use client";
import { Contact, Projects, Work } from "@/components";
import { motion } from "framer-motion";
import type { FC } from "react";
import { Blog } from "./Blog";
import { PostType } from "@/types/PostType";
interface MainProps {
posts: PostType[];
}
export const Main: FC<MainProps> = ({ posts }) => {
return (
<>
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: "easeOut", delay: 0.2 }}
viewport={{ once: true }}
>
<Work />
</motion.div>
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: "easeOut", delay: 0.4 }}
viewport={{ once: true }}
>
<Projects />
</motion.div>
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: "easeOut", delay: 0.4 }}
viewport={{ once: true }}
>
<Blog posts={posts} />
</motion.div>
<Contact />
</>
);
};
================================================
FILE: src/components/Projects.tsx
================================================
import { projects } from "@/data";
import type { FC } from "react";
import { GithubIcon, VisitIcon } from "./Icons";
export const Projects: FC = () => {
return (
<section className="py-12 px-6 md:py-12 mt-8" id="projects">
<h2 className="text-4xl font-light text-center mb-6 md:mb-8">Projects</h2>
<div className="max-w-4xl mx-auto space-y-8 md:space-y-8 px-4 md:px-0 pt-6">
{projects.map((project, index) => (
<div
key={index}
className="block border-l-4 border-neutral-700 pl-4 md:pl-4 hover:border-neutral-900 dark:hover:border-neutral-300 transition-all duration-200"
>
<div className="flex flex-col md:flex-row md:justify-between md:items-center gap-1 w-[90%] md:w-full">
<h3 className="text-xl md:text-2xl font-medium text-neutral-900 dark:text-neutral-100">
{project.title}
</h3>
<span className="text-neutral-400 text-xs md:text-sm">
{project.timeline}
</span>
</div>
<p className="text-neutral-500 text-base md:text-lg">
{project.description}
</p>
<div className="mt-2 text-xs md:text-sm text-neutral-400 flex space-x-4">
<a
href={project.url}
target="_blank"
rel="noopener noreferrer"
className="hover:text-neutral-900 dark:hover:text-neutral-100 transition flex items-center gap-1"
>
Live{" "}
<VisitIcon className="h-4 w-4 text-neutral-600 dark:text-neutral-400" />
</a>
<a
href={project.github}
target="_blank"
rel="noopener noreferrer"
className="hover:text-neutral-900 dark:hover:text-neutral-100 transition flex items-center gap-1"
>
GitHub{" "}
<GithubIcon className="h-4 w-4 text-neutral-600 dark:text-neutral-400" />
</a>
</div>
</div>
))}
</div>
</section>
);
};
================================================
FILE: src/components/Work.tsx
================================================
import { work } from "@/data";
import type { FC } from "react";
export const Work: FC = () => {
return (
<section className="py-12 px-6 md:py-12 mt-8" id="work">
<h2 className="text-4xl font-light text-center mb-4 md:mb-8">
Work Experience
</h2>
<div className="max-w-4xl mx-auto space-y-8 md:space-y-8 px-4 md:px-0 pt-6">
{work.map((item, index) => (
<a
key={index}
href={item.url}
target="_blank"
rel="noopener noreferrer"
className="block border-l-4 border-neutral-700 pl-4 md:pl-4 hover:border-neutral-900 dark:hover:border-neutral-300 transition-all duration-200"
>
<div className="flex flex-col md:flex-row md:justify-between md:items-center gap-1 w-[90%] md:w-full">
<h3 className="text-xl md:text-2xl font-medium text-neutral-900 dark:text-neutral-100">
{item.title}
</h3>
<span className="text-neutral-400 text-xs md:text-sm">
{item.timeline}
</span>
</div>
<p className="text-neutral-500 text-base md:text-lg">{item.role}</p>
<p className="text-neutral-400 text-xs md:text-sm mt-2">
{item.description}
</p>
</a>
))}
</div>
</section>
);
};
================================================
FILE: src/components/index.ts
================================================
export { Contact } from "./Contact";
export { Footer } from "./Footer";
export { Header } from "./Header";
export { Hero } from "./Hero";
export { Projects } from "./Projects";
export { Work } from "./Work";
export { Main } from "./Main";
================================================
FILE: src/components/theme-provider.tsx
================================================
"use client";
import { createContext, useContext, useEffect, useState } from "react";
type Theme = "dark" | "light";
type ThemeProviderProps = {
children: React.ReactNode;
};
type ThemeProviderState = {
theme: Theme;
setTheme: (theme: Theme) => void;
};
const initialState: ThemeProviderState = {
theme: "dark",
setTheme: () => null,
};
const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
export function ThemeProvider({ children }: ThemeProviderProps) {
const [theme, setTheme] = useState<Theme>("dark");
useEffect(() => {
// Check for saved theme preference
const savedTheme = localStorage.getItem("theme") as Theme | null;
// Check system preference
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light";
// Use saved theme if it exists, otherwise use system preference
const initialTheme = savedTheme || systemTheme;
setTheme(initialTheme);
// Listen for system theme changes
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = (e: MediaQueryListEvent) => {
// Only update if there's no saved preference
if (!localStorage.getItem("theme")) {
setTheme(e.matches ? "dark" : "light");
}
};
mediaQuery.addEventListener("change", handleChange);
return () => {
mediaQuery.removeEventListener("change", handleChange);
};
}, []);
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove("light", "dark");
root.classList.add(theme);
}, [theme]);
const value = {
theme,
setTheme: (theme: Theme) => {
localStorage.setItem("theme", theme);
setTheme(theme);
},
};
return (
<ThemeProviderContext.Provider value={value}>
{children}
</ThemeProviderContext.Provider>
);
}
export const useTheme = () => {
const context = useContext(ThemeProviderContext);
if (context === undefined)
throw new Error("useTheme must be used within a ThemeProvider");
return context;
};
================================================
FILE: src/components/theme-toggle.tsx
================================================
"use client";
import { useTheme } from "./theme-provider";
import { Moon, Sun } from "lucide-react";
import { useEffect, useState } from "react";
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
// Avoid hydration mismatch by ensuring component only renders after mounting
useEffect(() => setMounted(true), []);
if (!mounted) return null;
const isCurrentlyDark = theme === "dark";
const label = isCurrentlyDark ? "Switch to light mode" : "Switch to dark mode";
return (
<div className="flex items-center gap-2">
<button
onClick={() => setTheme(isCurrentlyDark ? "light" : "dark")}
className="relative rounded-md p-2 hover:bg-neutral-100 dark:hover:bg-neutral-800 flex items-center justify-center cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 dark:focus:ring-offset-background-dark transition-all duration-200"
aria-label={label}
title={label}
role="switch"
aria-checked={isCurrentlyDark}
>
<div className="relative w-5 h-5">
<Sun className="absolute inset-0 h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute inset-0 h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
</div>
<span className="sr-only">{label}</span>
</button>
</div>
);
}
================================================
FILE: src/data/index.ts
================================================
export { work } from "./work";
export { projects } from "./projects";
export { socialLinks } from "./social";
export { navLinks } from "./nav";
export { personalData } from "./personal";
================================================
FILE: src/data/nav.ts
================================================
export const navLinks = [
{ href: "#home", label: "Home" },
{ href: "#work", label: "Work" },
{ href: "#projects", label: "Projects" },
{ href: "#blog", label: "Blog" },
{ href: "#contact", label: "Contact" },
];
================================================
FILE: src/data/personal.ts
================================================
export const personalData = {
name: "Avneesh Agarwal",
designation: "Full Stack Web3 Developer",
metaDescription:
"Avneesh Agarwal - Full Stack Web3 Developer & CTO at Orcas. Expert in React, TypeScript, and developer tools. Explore my projects, articles, and open source contributions.",
about:
"Hey, I'm Avneesh Agarwal — a developer based in India, passionate about building powerful dev tools, contributing to open source, and sharing my learnings through writing. Currently, I'm the CTO at Orcas, where we're reshaping equity crowdfunding for startups. I've worked across multiple startups as a developer relations engineer, full-stack developer, and technical writer, helping teams build, scale, and engage with developer communities. When I'm not coding, you'll find me experimenting with side projects, writing articles, or diving into something completely random—just for the fun of it. Oh, and I'm also a sports enthusiast (fitness freak + nerd combo :p).",
shorterDesc:
"Full stack web3 developer and technical writer contributing to open source projects and teaching others, while building side projects every now and then.",
site: "https://avneesh.tech",
email: "hi@avneesh.tech",
x: "avneesh0612",
keywords: [
"software engineer",
"full-stack developer",
"Web3 developer",
"technical writer",
"developer relations",
"CTO",
"open source contributor",
"React developer",
"TypeScript",
"JavaScript",
"startup technology",
"developer tools",
"equity crowdfunding",
"India tech",
"tech blogger",
"Avneesh Agarwal",
],
blog: "https://blog.avneesh.tech",
};
================================================
FILE: src/data/projects.ts
================================================
export const projects = [
{
title: "Chessmates",
description:
"A team-based chess game where players vote on moves. The most popular choice determines the play, with points awarded for winning moves. Won three prizes at the ETH Global Frames Hackathon.",
timeline: "Mar 2024",
url: "https://ethglobal.com/showcase/chessmates-qt6d3",
github: "https://github.com/avneesh0612/Chessmates",
},
{
title: "tldrbot",
description:
"A Discord bot that summarizes conversations with a simple command. Recognized as 'Product of the Day' on Product Hunt and integrated into 100+ servers within the first week.",
timeline: "Feb 2023",
url: "https://www.producthunt.com/products/tldrbot#tldrbot",
github: "https://github.com/avneesh0612/tldr-bot",
},
{
title: "Snipli",
description: "Convert your local files into a gist in just a snap",
timeline: "May 2022",
url: "https://www.producthunt.com/products/snipli#snipli",
github: "https://github.com/0xMukesh/snipli",
},
{
title: "React and Next.js Snippets",
description:
"A VSCode extension that eliminates repetitive boilerplate code. Awarded 'Product of the Day' on Product Hunt and currently serves over 24,000 users.",
timeline: "Feb 2022",
url: "https://www.producthunt.com/products/react-and-next-js-snippets#react-and-next-js-snippets",
github: "https://github.com/avneesh0612/react-nextjs-snippets",
},
];
================================================
FILE: src/data/social.tsx
================================================
import {
FarcasterIcon,
GithubIcon,
LinkedInIcon,
MailIcon,
XIcon,
} from "@/components/Icons";
import { personalData } from "./personal";
export const socialLinks = [
{
name: "GitHub",
Icon: GithubIcon,
link: "https://github.com/avneesh0612",
},
{
name: "X",
Icon: XIcon,
link: "https://x.com/avneesh0612",
},
{
name: "Farcaster",
Icon: FarcasterIcon,
link: "https://warpcast.com/avneesh",
},
{
name: "Mail me",
Icon: MailIcon,
link: `mailto:${personalData.email}`,
},
{
name: "LinkedIn",
Icon: LinkedInIcon,
link: "https://www.linkedin.com/in/avneesh0612/",
},
];
================================================
FILE: src/data/work.ts
================================================
export const work = [
{
title: "Orcas",
role: "CTO",
description:
"Leading the development of a crowdfunding equity platform for startups.",
timeline: "Oct 2024 - Present",
url: "https://orcas.com",
},
{
title: "Neynar",
role: "Developer Relations Engineer",
description:
"Managed product documentation, wrote guides, and published case studies to enhance the developer experience.",
timeline: "Apr 2024 - Nov 2024",
url: "https://neynar.com",
},
{
title: "thirdweb",
role: "Developer Relations Engineer",
description:
"Published 60+ guides, created templates, mentored developers at hackathons, and collaborated across departments.",
timeline: "Apr 2022 - Feb 2024",
url: "https://thirdweb.com",
},
{
title: "Yoke (NIL CLUB)",
role: "Full Stack Engineer",
description:
"Built a web3 payment system, developed the front end for NIL clubs, and refactored JavaScript codebase to TypeScript.",
timeline: "Jan 2022 - Sep 2022",
url: "https://nilclub.com",
},
{
title: "Freelancer",
role: "Technical Writer & Full Stack Developer",
description:
"Created technical content for Logrocket, Medusa, and Pointer. Worked on projects like Candypay, Tinydancer, and Cubik.",
timeline: "Jan 2022 - Present",
url: "",
},
];
================================================
FILE: src/types/PostType.ts
================================================
export interface PostType {
data: {
post: {
_id: string;
title: string;
content: string;
brief: string;
totalReactions: number;
replyCount: number;
responseCount: number;
coverImage: { url: string };
slug: string;
popularity: number;
reactionCount: number;
readTimeInMinutes: number;
};
};
}
================================================
FILE: src/utils/getPosts.ts
================================================
const getUserDataAndPosts = async (username: string) => {
const ids = [];
const userDataQuery = `
{
user(username:"${username}"){
username,
posts(pageSize:3,page:1,filter:{publications:["60d17a93a6a3a25dadf6268d"]}) {
edges {
node {
id
}
}
}
}
}
`;
const userDataRes = await fetch("https://gql.hashnode.com/", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ query: userDataQuery }),
});
const userData = await userDataRes.json();
const edges = userData.data.user.posts.edges;
for (let i = 0; i < edges.length; i++) {
ids.push(edges[i].node.id);
}
const posts = await Promise.all(
ids.map(async (id) => {
const postQuery = `
{
post(id: "${id}") {
id
title
title
brief
slug
reactionCount
replyCount
responseCount
brief
coverImage{
url
}
readTimeInMinutes
}
}
`;
const postRes = await fetch("https://gql.hashnode.com/", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ query: postQuery }),
});
const postData = await postRes.json();
return postData;
})
);
return posts;
};
export default getUserDataAndPosts;
================================================
FILE: tailwind.config.ts
================================================
import type { Config } from "tailwindcss";
import defaultTheme from "tailwindcss/defaultTheme";
export default {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
darkMode: "selector",
theme: {
extend: {
fontFamily: {
geomanist: ["Geomanist", ...defaultTheme.fontFamily.sans],
},
colors: {
primary: {
DEFAULT: "#3B82F6",
hover: "#2563EB",
},
accent: {
first: "#F59E0B",
second: "#10B981",
third: "#EC4899",
},
background: {
light: "#fafafa",
dark: "#0a0a0a",
},
foreground: {
light: "#0a0a0a",
dark: "#ededed",
},
neutral: {
100: "#f5f5f5",
200: "#e5e5e5",
300: "#d4d4d4",
400: "#a3a3a3",
500: "#737373",
600: "#525252",
700: "#404040",
800: "#262626",
900: "#171717",
},
},
},
},
plugins: [],
} satisfies Config;
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
gitextract_38gvouyj/ ├── .gitignore ├── LICENSE ├── README.md ├── eslint.config.mjs ├── next.config.ts ├── package.json ├── postcss.config.mjs ├── public/ │ ├── fonts/ │ │ ├── Geomanist-Regular-Italic.otf │ │ └── Geomanist-Regular.otf │ ├── robots.txt │ ├── rss.xml │ └── sitemap.xml ├── src/ │ ├── app/ │ │ ├── globals.css │ │ ├── layout.tsx │ │ └── page.tsx │ ├── components/ │ │ ├── Blog.tsx │ │ ├── Contact.tsx │ │ ├── Footer.tsx │ │ ├── Header.tsx │ │ ├── Hero.tsx │ │ ├── Icons/ │ │ │ ├── CrossIcon.tsx │ │ │ ├── FarcasterIcon.tsx │ │ │ ├── GithubIcon.tsx │ │ │ ├── LinkedInIcon.tsx │ │ │ ├── Logo.tsx │ │ │ ├── MailIcon.tsx │ │ │ ├── MenuIcon.tsx │ │ │ ├── VisitIcon.tsx │ │ │ ├── XIcon.tsx │ │ │ └── index.ts │ │ ├── Main.tsx │ │ ├── Projects.tsx │ │ ├── Work.tsx │ │ ├── index.ts │ │ ├── theme-provider.tsx │ │ └── theme-toggle.tsx │ ├── data/ │ │ ├── index.ts │ │ ├── nav.ts │ │ ├── personal.ts │ │ ├── projects.ts │ │ ├── social.tsx │ │ └── work.ts │ ├── types/ │ │ └── PostType.ts │ └── utils/ │ └── getPosts.ts ├── tailwind.config.ts └── tsconfig.json
SYMBOL INDEX (11 symbols across 7 files)
FILE: src/app/layout.tsx
function RootLayout (line 75) | function RootLayout({
FILE: src/app/page.tsx
function getPosts (line 6) | async function getPosts() {
function Home (line 34) | async function Home() {
FILE: src/components/Blog.tsx
type PostsType (line 5) | interface PostsType {
FILE: src/components/Main.tsx
type MainProps (line 9) | interface MainProps {
FILE: src/components/theme-provider.tsx
type Theme (line 5) | type Theme = "dark" | "light";
type ThemeProviderProps (line 7) | type ThemeProviderProps = {
type ThemeProviderState (line 11) | type ThemeProviderState = {
function ThemeProvider (line 23) | function ThemeProvider({ children }: ThemeProviderProps) {
FILE: src/components/theme-toggle.tsx
function ThemeToggle (line 7) | function ThemeToggle() {
FILE: src/types/PostType.ts
type PostType (line 1) | interface PostType {
Condensed preview — 46 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (52K chars).
[
{
"path": ".gitignore",
"chars": 480,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2025 Avneesh Agarwal\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "README.md",
"chars": 1131,
"preview": "<h1 align=\"center\">Portfolio</h1>\n<p>\n <a href=\"https://github.com/avneesh0612/portfolio/blob/main/LICENSE\" target=\"_"
},
{
"path": "eslint.config.mjs",
"chars": 393,
"preview": "import { dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { FlatCompat } from \"@eslint/eslintrc\";\n\ncon"
},
{
"path": "next.config.ts",
"chars": 133,
"preview": "import type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n /* config options here */\n};\n\nexport default"
},
{
"path": "package.json",
"chars": 814,
"preview": "{\n \"name\": \"portfolio\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"next dev --turbopack\",\n "
},
{
"path": "postcss.config.mjs",
"chars": 81,
"preview": "const config = {\n plugins: [\"@tailwindcss/postcss\"],\n};\n\nexport default config;\n"
},
{
"path": "public/robots.txt",
"chars": 23,
"preview": "User-agent: *\nDisallow:"
},
{
"path": "public/rss.xml",
"chars": 1697,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rss version=\"2.0\">\n <channel>\n <title>Avneesh Agarwal</title>\n "
},
{
"path": "public/sitemap.xml",
"chars": 242,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n <url>\n <l"
},
{
"path": "src/app/globals.css",
"chars": 1274,
"preview": "@import \"tailwindcss\";\n@config \"../../tailwind.config.ts\";\n\n:root {\n --background: theme(\"colors.background.light\");\n "
},
{
"path": "src/app/layout.tsx",
"chars": 2257,
"preview": "import { Footer, Header } from \"@/components\";\nimport { ThemeProvider } from \"@/components/theme-provider\";\nimport { per"
},
{
"path": "src/app/page.tsx",
"chars": 1226,
"preview": "import { Hero, Main } from \"@/components\";\nimport { personalData, socialLinks } from \"@/data\";\nimport getUserDataAndPost"
},
{
"path": "src/components/Blog.tsx",
"chars": 2609,
"preview": "import { personalData } from \"@/data\";\nimport { PostType } from \"@/types/PostType\";\nimport type { FC } from \"react\";\n\nin"
},
{
"path": "src/components/Contact.tsx",
"chars": 1201,
"preview": "import { socialLinks } from \"@/data\";\nimport type { FC } from \"react\";\n\nexport const Contact: FC = () => {\n return (\n "
},
{
"path": "src/components/Footer.tsx",
"chars": 543,
"preview": "import { personalData } from \"@/data\";\nimport type { FC } from \"react\";\n\nexport const Footer: FC = () => {\n const curre"
},
{
"path": "src/components/Header.tsx",
"chars": 3608,
"preview": "\"use client\";\n\nimport { navLinks } from \"@/data\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { Menu"
},
{
"path": "src/components/Hero.tsx",
"chars": 4396,
"preview": "import { personalData } from \"@/data\";\nimport Image from \"next/image\";\nimport type { FC } from \"react\";\nimport { RoughNo"
},
{
"path": "src/components/Icons/CrossIcon.tsx",
"chars": 579,
"preview": "import React from \"react\";\n\nexport const CrossIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n fi"
},
{
"path": "src/components/Icons/FarcasterIcon.tsx",
"chars": 1233,
"preview": "import React from \"react\";\n\nexport const FarcasterIcon: React.FC<React.SVGProps<SVGSVGElement>> = (\n props\n) => (\n <sv"
},
{
"path": "src/components/Icons/GithubIcon.tsx",
"chars": 836,
"preview": "import React from \"react\";\n\nexport const GithubIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n x"
},
{
"path": "src/components/Icons/LinkedInIcon.tsx",
"chars": 475,
"preview": "import React from \"react\";\n\nexport const LinkedInIcon: React.FC<React.SVGProps<SVGSVGElement>> = (\n props\n) => (\n <svg"
},
{
"path": "src/components/Icons/Logo.tsx",
"chars": 564,
"preview": "import React from \"react\";\n\nconst Logo: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n width=\"24\"\n "
},
{
"path": "src/components/Icons/MailIcon.tsx",
"chars": 593,
"preview": "import React from \"react\";\n\nexport const MailIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n xml"
},
{
"path": "src/components/Icons/MenuIcon.tsx",
"chars": 618,
"preview": "import React from \"react\";\n\nexport const MenuIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n wid"
},
{
"path": "src/components/Icons/VisitIcon.tsx",
"chars": 887,
"preview": "import React from \"react\";\n\nexport const VisitIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n cl"
},
{
"path": "src/components/Icons/XIcon.tsx",
"chars": 577,
"preview": "import React from \"react\";\n\nexport const XIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n xmlns="
},
{
"path": "src/components/Icons/index.ts",
"chars": 252,
"preview": "export { GithubIcon } from \"./GithubIcon\";\nexport { VisitIcon } from \"./VisitIcon\";\nexport { MailIcon } from \"./MailIcon"
},
{
"path": "src/components/Main.tsx",
"chars": 1136,
"preview": "\"use client\";\n\nimport { Contact, Projects, Work } from \"@/components\";\nimport { motion } from \"framer-motion\";\nimport ty"
},
{
"path": "src/components/Projects.tsx",
"chars": 2134,
"preview": "import { projects } from \"@/data\";\nimport type { FC } from \"react\";\nimport { GithubIcon, VisitIcon } from \"./Icons\";\n\nex"
},
{
"path": "src/components/Work.tsx",
"chars": 1363,
"preview": "import { work } from \"@/data\";\nimport type { FC } from \"react\";\n\nexport const Work: FC = () => {\n return (\n <section"
},
{
"path": "src/components/index.ts",
"chars": 239,
"preview": "export { Contact } from \"./Contact\";\nexport { Footer } from \"./Footer\";\nexport { Header } from \"./Header\";\nexport { Hero"
},
{
"path": "src/components/theme-provider.tsx",
"chars": 2103,
"preview": "\"use client\";\n\nimport { createContext, useContext, useEffect, useState } from \"react\";\n\ntype Theme = \"dark\" | \"light\";\n\n"
},
{
"path": "src/components/theme-toggle.tsx",
"chars": 1469,
"preview": "\"use client\";\n\nimport { useTheme } from \"./theme-provider\";\nimport { Moon, Sun } from \"lucide-react\";\nimport { useEffect"
},
{
"path": "src/data/index.ts",
"chars": 187,
"preview": "export { work } from \"./work\";\nexport { projects } from \"./projects\";\nexport { socialLinks } from \"./social\";\nexport { n"
},
{
"path": "src/data/nav.ts",
"chars": 223,
"preview": "export const navLinks = [\n { href: \"#home\", label: \"Home\" },\n { href: \"#work\", label: \"Work\" },\n { href: \"#projects\","
},
{
"path": "src/data/personal.ts",
"chars": 1663,
"preview": "export const personalData = {\n name: \"Avneesh Agarwal\",\n designation: \"Full Stack Web3 Developer\",\n metaDescription:\n"
},
{
"path": "src/data/projects.ts",
"chars": 1462,
"preview": "export const projects = [\n {\n title: \"Chessmates\",\n description:\n \"A team-based chess game where players vot"
},
{
"path": "src/data/social.tsx",
"chars": 657,
"preview": "import {\n FarcasterIcon,\n GithubIcon,\n LinkedInIcon,\n MailIcon,\n XIcon,\n} from \"@/components/Icons\";\nimport { perso"
},
{
"path": "src/data/work.ts",
"chars": 1359,
"preview": "export const work = [\n {\n title: \"Orcas\",\n role: \"CTO\",\n description:\n \"Leading the development of a crow"
},
{
"path": "src/types/PostType.ts",
"chars": 376,
"preview": "export interface PostType {\n data: {\n post: {\n _id: string;\n title: string;\n content: string;\n b"
},
{
"path": "src/utils/getPosts.ts",
"chars": 1357,
"preview": "const getUserDataAndPosts = async (username: string) => {\n const ids = [];\n\n const userDataQuery = `\n {\n user(usern"
},
{
"path": "tailwind.config.ts",
"chars": 1126,
"preview": "import type { Config } from \"tailwindcss\";\nimport defaultTheme from \"tailwindcss/defaultTheme\";\n\nexport default {\n cont"
},
{
"path": "tsconfig.json",
"chars": 602,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2017\",\n \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n \"allowJs\": true,\n "
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the avneesh0612/portfolio GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 46 files (46.1 KB), approximately 14.1k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.