feat: projects + socials added

Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
Ameya Shenoy 2025-06-26 01:24:16 +05:30
parent 1798d390e1
commit 898a236510
6 changed files with 210 additions and 6 deletions

View file

@ -11,6 +11,7 @@
"@iconify/react": "^6.0.0", "@iconify/react": "^6.0.0",
"@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.7",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dompurify": "^3.2.6", "dompurify": "^3.2.6",
@ -1203,6 +1204,40 @@
} }
} }
}, },
"node_modules/@radix-ui/react-tooltip": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz",
"integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.2",
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-dismissable-layer": "1.1.10",
"@radix-ui/react-id": "1.1.1",
"@radix-ui/react-popper": "1.2.7",
"@radix-ui/react-portal": "1.1.9",
"@radix-ui/react-presence": "1.1.4",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-slot": "1.2.3",
"@radix-ui/react-use-controllable-state": "1.2.2",
"@radix-ui/react-visually-hidden": "1.2.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": { "node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
@ -1324,6 +1359,29 @@
} }
} }
}, },
"node_modules/@radix-ui/react-visually-hidden": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-primitive": "2.1.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/rect": { "node_modules/@radix-ui/rect": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",

View file

@ -12,6 +12,7 @@
"@iconify/react": "^6.0.0", "@iconify/react": "^6.0.0",
"@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.7",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dompurify": "^3.2.6", "dompurify": "^3.2.6",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 779 KiB

View file

@ -2,6 +2,11 @@ import { MapPin, Code, Briefcase, Download } from "lucide-react";
import { headers } from "next/headers"; import { headers } from "next/headers";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import Link from "next/link"; import Link from "next/link";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
export default async function Portfolio() { export default async function Portfolio() {
// const headersList = await headers(); // const headersList = await headers();
@ -92,6 +97,14 @@ export default async function Portfolio() {
}, },
}; };
const featuredProjects = [
{
name: "Semaphore Chat",
link: "https://semaphore.chat",
summary: `The is a chat application that offers a streamlined, no-nonsense AI chat experience. It provides access to multiple large language models (LLMs) from various vendors. Key features include markdown rendering of AI outputs, syntax highlighting for code, and the ability to display Mermaid.js diagrams on a canvas. The app supports real-time synchronization and resumable streams using Zero (sync engine), enabling users to share links, and allows for collaborative use of LLMs with peers. Authentication is handled via Google OAuth, the database is Postgres, frontend is in NextJS, self-hosted on an Hetzner server`,
},
];
const workExperience = [ const workExperience = [
{ {
company: "Grapevine", company: "Grapevine",
@ -145,6 +158,32 @@ export default async function Portfolio() {
}, },
]; ];
const socials = [
{
icon: "pajamas:mail",
link: "mailto:shenoy.ameya@gmail.com",
hoverText: "Shoot me an email!",
},
{
icon: "pajamas:linkedin",
link: "https://linkedin.com/in/codingcoffee",
hoverText: "Let's connect on LinkedIn",
},
{
icon: "pajamas:github",
link: "https://github.com/codingcoffee",
hoverText: "Checkout my opensource repos at GitHub",
},
{
icon: "pajamas:twitter",
link: "https://x.com/codingcoffeeX",
hoverText: "Follow me on X!",
},
];
return ( return (
<main className="flex items-top justify-center font-[family-name:var(--font-spacegrotesk-sans)] pt-10 md:pt-20 pb-25 md:pb-0"> <main className="flex items-top justify-center font-[family-name:var(--font-spacegrotesk-sans)] pt-10 md:pt-20 pb-25 md:pb-0">
<div className=""> <div className="">
@ -183,10 +222,30 @@ export default async function Portfolio() {
</div> </div>
</div> </div>
<div className="md:text-2xl/10 text-xl/8 pb-20"> <div className="md:text-2xl/10 text-xl/8 pb-20">
Engineering lead with 8+ years of expertise in designing scalable <div className="pb-5">
system architecture, leading high performing teams, and delivering Engineering lead with 8+ years of expertise in designing scalable
ai driven solutions while also maintaining the role of an individual system architecture, leading high performing teams, and delivering
contributor. ai driven solutions while also maintaining the role of an
individual contributor.
</div>
<div className="flex text-red-500 gap-5">
{socials.map((social, _) => (
<Tooltip>
<TooltipTrigger asChild>
<Link
href={social.link}
target="_blank"
rel="noopener noreferrer"
>
<Icon icon={social.icon} className="inline-block" />
</Link>
</TooltipTrigger>
<TooltipContent>
<p className="text-xl">{social.hoverText}</p>
</TooltipContent>
</Tooltip>
))}
</div>
</div> </div>
</div> </div>
<div className="md:w-[40vw] w-[95vw] md:min-w-3xl"> <div className="md:w-[40vw] w-[95vw] md:min-w-3xl">
@ -211,6 +270,28 @@ export default async function Portfolio() {
</div> </div>
))} ))}
</div> </div>
<div className="md:w-[40vw] w-[95vw] md:min-w-3xl">
<div className="text-3xl pb-10">Featured Projects</div>
{featuredProjects.map((project, index) => (
<div key={index} className="">
<div className="flex items-center justify-between pb-5">
<Link
href={project.link}
target="_blank"
rel="noopener noreferrer"
className="text-xl underline"
>
<p className="text-2xl text-red-500">{project.name}</p>
</Link>
</div>
<p className="text-gray-500 dark:text-gray-100 text-justify text-xl/8 pb-8">
{project.summary}
</p>
</div>
))}
</div>
<div className="md:w-[40vw] w-[95vw] md:min-w-3xl"> <div className="md:w-[40vw] w-[95vw] md:min-w-3xl">
<div className="text-3xl pb-10 gap-10">Key Skills</div> <div className="text-3xl pb-10 gap-10">Key Skills</div>
<div className="grid grid-cols-1 md:grid-cols-2"> <div className="grid grid-cols-1 md:grid-cols-2">
@ -225,7 +306,10 @@ export default async function Portfolio() {
key={language} key={language}
className="flex items-center px-3 py-1 rounded-full gap-2" className="flex items-center px-3 py-1 rounded-full gap-2"
> >
<Icon icon={icon as string} className="inline-block" />{" "} <Icon
icon={icon as string}
className="inline-block"
/>{" "}
{language} {language}
</span> </span>
))} ))}

View file

@ -45,7 +45,7 @@ export function NavigationMenu() {
variant="ghost" variant="ghost"
className={`${pathname === "/portfolio" ? "text-red-500" : ""} text-xl`} className={`${pathname === "/portfolio" ? "text-red-500" : ""} text-xl`}
> >
<div className="hidden md:inline">Portfolio</div> <div className="hidden md:inline">Work</div>
<div className="md:hidden"> <div className="md:hidden">
<BriefcaseBusiness style={{ width: "27px", height: "27px" }} /> <BriefcaseBusiness style={{ width: "27px", height: "27px" }} />
</div> </div>

View file

@ -0,0 +1,61 @@
"use client"
import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import { cn } from "@/lib/utils"
function TooltipProvider({
delayDuration = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
)
}
function Tooltip({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
)
}
function TooltipTrigger({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}
function TooltipContent({
className,
sideOffset = 0,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
className={cn(
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
)
}
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }