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
================================================
Portfolio
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
================================================
Avneesh Agarwal
https://avneesh.tech/
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).
Thurs, 20 Mar 2025 12:00:00 GMT
https://validator.w3.org/feed/docs/rss2.html
https://github.com/jpmonette/feed
en
Avneesh Agarwal
https://avneesh.tech/about.png
https://avneesh.tech/
All rights reserved, Avneesh Agarwal
Technology
Programming
Web Development
Web3 development
Blogger
Avneesh Agarwal
================================================
FILE: public/sitemap.xml
================================================
https://avneesh.tech/
2025-03-20
1.0
================================================
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 (
{children}
);
}
================================================
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 = {
"@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 (
);
}
================================================
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 = ({ posts }) => {
return (
);
};
================================================
FILE: src/components/Contact.tsx
================================================
import { socialLinks } from "@/data";
import type { FC } from "react";
export const Contact: FC = () => {
return (
);
};
================================================
FILE: src/components/Footer.tsx
================================================
import { personalData } from "@/data";
import type { FC } from "react";
export const Footer: FC = () => {
const currentYear = new Date().getFullYear();
return (
);
};
================================================
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 (
);
};
================================================
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 (
Hey, I'm{" "}
{personalData.name}
— 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{" "}
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 :p.
{" "}
Got a startup that needs someone like me?{" "}
Let's talk!
);
};
================================================
FILE: src/components/Icons/CrossIcon.tsx
================================================
import React from "react";
export const CrossIcon: React.FC> = (props) => (
);
================================================
FILE: src/components/Icons/FarcasterIcon.tsx
================================================
import React from "react";
export const FarcasterIcon: React.FC> = (
props
) => (
);
================================================
FILE: src/components/Icons/GithubIcon.tsx
================================================
import React from "react";
export const GithubIcon: React.FC> = (props) => (
);
================================================
FILE: src/components/Icons/LinkedInIcon.tsx
================================================
import React from "react";
export const LinkedInIcon: React.FC> = (
props
) => (
);
================================================
FILE: src/components/Icons/Logo.tsx
================================================
import React from "react";
const Logo: React.FC> = (props) => (
);
export default Logo;
================================================
FILE: src/components/Icons/MailIcon.tsx
================================================
import React from "react";
export const MailIcon: React.FC> = (props) => (
);
================================================
FILE: src/components/Icons/MenuIcon.tsx
================================================
import React from "react";
export const MenuIcon: React.FC> = (props) => (
);
================================================
FILE: src/components/Icons/VisitIcon.tsx
================================================
import React from "react";
export const VisitIcon: React.FC> = (props) => (
);
================================================
FILE: src/components/Icons/XIcon.tsx
================================================
import React from "react";
export const XIcon: React.FC> = (props) => (
);
================================================
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 = ({ posts }) => {
return (
<>
>
);
};
================================================
FILE: src/components/Projects.tsx
================================================
import { projects } from "@/data";
import type { FC } from "react";
import { GithubIcon, VisitIcon } from "./Icons";
export const Projects: FC = () => {
return (
Projects
{projects.map((project, index) => (
{project.title}
{project.timeline}
{project.description}
))}
);
};
================================================
FILE: src/components/Work.tsx
================================================
import { work } from "@/data";
import type { FC } from "react";
export const Work: FC = () => {
return (
);
};
================================================
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(initialState);
export function ThemeProvider({ children }: ThemeProviderProps) {
const [theme, setTheme] = useState("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 (
{children}
);
}
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 (
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}
>
{label}
);
}
================================================
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"]
}