portfolio / src /components /Projects.jsx
kumar-aditya's picture
Update src/components/Projects.jsx
bc82223 verified
import React from "react";
import { TbExternalLink } from "react-icons/tb";
import { motion } from "framer-motion";
const projects = [
{
id: 1,
title: "Multi-Platform Document Intelligence App",
status: "In progress",
description: (
<>
Cross-platform client that uploads documents and returns{" "}
<span className="font-semibold">entity extraction</span>,{" "}
<span className="font-semibold">concise summaries</span>, and{" "}
<span className="font-semibold">semantic search</span> using an LLM-backed
extraction & embedding service. Design includes client-side indexing,
secure uploads, vector search, and cloud sync for offline-first usage.
</>
),
tech: [
"Kotlin Multiplatform",
"Compose Multiplatform",
"Ktor",
"Supabase",
"Docker",
"Embeddings / LLM",
],
image: "/assets/project-doc.png",
link: "#"
},
{
id: 2,
title: "End-to-End Media Processing Pipeline",
status: "Prototype",
description: (
<>
Asynchronous processing pipeline for uploaded media: resilient{" "}
<span className="font-semibold">transcoding</span>,{" "}
<span className="font-semibold">speech-to-text</span> (Whisper / ASR),
AI-powered <span className="font-semibold">moderation & summarization</span>,
and webhook/push notifications. Built for horizontal scale and fault
tolerance with signed artifact URLs for clients.
</>
),
tech: [
"Ktor",
"FFmpeg",
"Whisper / ASR",
"Redis / RabbitMQ",
"S3 / Supabase",
"Docker workers",
],
image: "/assets/project-media.png",
link: "#"
},
{
id: 3,
title: "Hermetic Reproducible ML Pipelines (MLOps PoC)",
status: "Prototype",
description: (
<>
Hermetic, reproducible training + serving setup: Dockerized training
environments, deterministic seeds, dataset versioning, experiment
tracking with <span className="font-semibold">MLflow</span>, and REST
inference endpoints for stable model deployment and CI-driven retraining.
</>
),
tech: [
"Docker",
"Python",
"PyTorch / scikit-learn",
"MLflow",
"GitHub Actions",
"Ktor (inference)",
],
image: "/assets/project-mlops.png",
link: "#"
}
];
export default function Projects() {
return (
<section
id="projects"
className="bg-black px-5 lg:px-28 py-10 lg:py-16 text-white"
aria-label="Projects"
>
<h2 className="text-2xl lg:text-4xl text-center">
My <span className="font-extrabold">Projects</span>
</h2>
<div className="mt-10 lg:mt-16 space-y-12">
{projects.map((project, index) => (
<motion.article
key={project.id}
className={`flex flex-col items-center gap-8 lg:gap-12 ${
index % 2 === 0 ? "lg:flex-row" : "lg:flex-row-reverse"
}`}
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ type: "spring", stiffness: 80, damping: 12, delay: index * 0.15 }}
viewport={{ once: true }}
>
{/* Image */}
<div className="lg:w-1/2 w-full rounded-2xl overflow-hidden shadow-lg">
<img
src={project.image}
alt={`${project.title} screenshot`}
className="w-full h-64 lg:h-80 object-cover transform hover:scale-105 transition-transform duration-500"
loading="lazy"
/>
</div>
{/* Content */}
<div className="lg:w-1/2 w-full">
<div className="flex items-start justify-between">
<div>
<h3 className="text-3xl lg:text-4xl font-extrabold">
{String(project.id).padStart(2, "0")}
</h3>
<p className="mt-1 text-xl lg:text-2xl font-bold">{project.title}</p>
</div>
<div className="text-sm lg:text-base">
<span className="inline-block bg-white/10 px-3 py-1 rounded-full text-white/90 text-xs lg:text-sm">
{project.status}
</span>
</div>
</div>
<p className="mt-4 text-sm lg:text-base text-gray-300 leading-relaxed">
{project.description}
</p>
{/* Tech badges */}
<div className="mt-4 flex flex-wrap gap-2">
{project.tech.map((t) => (
<span
key={t}
className="text-xs lg:text-sm bg-white/6 border border-white/8 px-2 py-1 rounded-md text-gray-200"
>
{t}
</span>
))}
</div>
{/* Links */}
<div className="mt-4 flex items-center gap-4">
<a
href={project.link}
className="inline-flex items-center gap-2 text-white hover:underline"
target="_blank"
rel="noopener noreferrer"
aria-label={`Open ${project.title} link`}
>
<TbExternalLink size={20} />
<span className="text-sm lg:text-base">View Repo / Demo</span>
</a>
</div>
</div>
</motion.article>
))}
</div>
</section>
);
}