Spaces:
Sleeping
Sleeping
File size: 5,572 Bytes
bc82223 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
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>
);
}
|