File size: 17,794 Bytes
046198b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { ExternalLink, FileText, Github, Linkedin } from "lucide-react";
import { CONTACT_EMAIL, GITHUB_URL, HUGGING_FACE_URL, LINKEDIN_URL } from "@/lib/links";

type Project = {
  id: string;
  era: "UNT - Graduate" | "Accenture" | "Undergrad" | "Independent";
  title: string;
  tagline: string;
  period: string;
  details: string[];
  stack: string[];
  links?: {
    label: string;
    href: string;
  }[];
};

const projects: Project[] = [
  {
    id: "alive-agents",
    era: "Independent",
    title: "Alive - AI Agent Orchestrator",
    tagline: "Full-stack platform that assembles AI dev teams for any coding task.",
    period: "2026",
    details: [
      "Spawns 5 role-based agents (Team Lead, Architect, FE Dev, BE Dev, Tester) per project.",
      "Each agent runs on a different AI provider (DeepSeek, Qwen, Kimi, GLM, GPT) - all in parallel.",
      "Isolated git worktrees per agent, real-time progress tracking, and live iframe preview.",
    ],
    stack: ["TypeScript", "Next.js", "Multi-Agent AI", "React", "Prisma"],
    links: [
      {
        label: "View Code",
        href: "https://github.com/im-mj/Agents-",
      },
    ],
  },
  {
    id: "nimbus-bank",
    era: "Independent",
    title: "Nimbus Bank - AI Triage System",
    tagline: "LangGraph multi-agent pipeline for banking customer support.",
    period: "Apr 2026",
    details: [
      "Built a LangGraph multi-agent system to classify and route banking support tickets.",
      "Agents handle intent detection, policy lookup, escalation, and resolution - end to end.",
      "Delivered full PRD, architecture diagram, and live Streamlit demo for Wipro pre-screening.",
    ],
    stack: ["Python", "LangGraph", "LLM", "Streamlit", "Multi-Agent"],
    links: [
      {
        label: "View Code",
        href: "https://github.com/im-mj/Nimbus-Bank-Triage",
      },
    ],
  },
  {
    id: "ghost-job-hunter",
    era: "Independent",
    title: "Ghost Job Hunter",
    tagline: "Chrome extension concept for spotting suspicious or stale job posts.",
    period: "2026",
    details: [
      "Flags ghost-job warning signs such as stale listings, repeated postings, vague role signals, and weak hiring intent.",
      "Uses an AI-assisted scoring flow to help job seekers focus on real opportunities instead of wasting applications.",
      "Connects analytics, recruiting pain points, and browser automation into a practical job-search tool.",
    ],
    stack: ["Chrome Extension", "JavaScript", "AI Scoring", "Job Analytics"],
    links: [
      {
        label: "View Code",
        href: "https://github.com/im-mj/Ghost-Job-Hunter",
      },
    ],
  },
  {
    id: "smartscreen",
    era: "UNT - Graduate",
    title: "SmartScreen - AI Resume Analyzer",
    tagline: "AI-driven resume scoring & ATS-match feedback.",
    period: "Jan 2025 - May 2025",
    details: [
      "Designed an AI scoring engine that grades resumes against a target JD and highlights ATS-killing gaps.",
      "Generates targeted feedback so candidates can iterate quickly instead of guessing.",
      "Built as an end-to-end concept: parsing -> scoring -> recommendations.",
    ],
    stack: ["Python", "NLP", "AI", "Data Analysis"],
  },
  {
    id: "cvs",
    era: "UNT - Graduate",
    title: "CVS Pharmacy Strategy Thesis",
    tagline: "Analytics-backed strategy across Finance, Marketing, Ops, HR & AI.",
    period: "Jan 2025 - May 2025",
    details: [
      "Deep-dived 10-K filings and market data to build a cross-functional growth thesis.",
      "Layered AI/automation recommendations on top of traditional strategy frames.",
      "Delivered as a board-style presentation with prioritized initiatives.",
    ],
    stack: ["Research", "10-K Analysis", "Strategy", "Presentations"],
  },
  {
    id: "jobs",
    era: "UNT - Graduate",
    title: "Job Market Analysis",
    tagline: "Interactive Tableau dashboards on hiring trends & skills demand.",
    period: "Aug 2024 - Dec 2024",
    details: [
      "Cleaned and modeled a multi-source job postings dataset.",
      "Built dashboards that surface skill demand, salary bands, and role trajectories.",
      "Designed for non-technical stakeholders to filter and self-serve.",
    ],
    stack: ["Tableau", "Data Viz", "SQL"],
  },
  {
    id: "spend",
    era: "UNT - Graduate",
    title: "Student Spending Analysis",
    tagline: "Regression + ANOVA on monthly student spend patterns.",
    period: "Aug 2024 - Dec 2024",
    details: [
      "Collected and cleaned a primary dataset from student respondents.",
      "Used regression and ANOVA to identify which factors actually moved spend.",
      "Translated stats into plain-English recommendations.",
    ],
    stack: ["Minitab", "Excel", "Statistics"],
  },
  {
    id: "smile",
    era: "UNT - Graduate",
    title: "Smile Buddy 3000 - Marketing Concept",
    tagline: "Superhero-themed product campaign with positioning + messaging.",
    period: "Jul 2025 - Sep 2025",
    details: [
      "Built persona, value prop, and a launch narrative around a fun mascot.",
      "Designed campaign assets and a phased go-to-market plan.",
    ],
    stack: ["Marketing Strategy", "Brand", "Advertising"],
  },
  {
    id: "secondlife",
    era: "UNT - Graduate",
    title: "Second Life - Organ Matching ML",
    tagline: "ML pipeline for patient-organ matching and hospital triage.",
    period: "2025",
    details: [
      "Built end-to-end ML pipeline with tiered matching, feature engineering, and model evaluation.",
      "Modeled patient and hospital journeys; benchmarked classifiers for match scoring accuracy.",
      "Deployed on HuggingFace Spaces with full architecture diagrams and a presentation deck.",
    ],
    stack: ["Python", "ML", "Flask", "SQL", "HuggingFace"],
    links: [
      {
        label: "View Code",
        href: "https://github.com/im-mj/SecondLife",
      },
    ],
  },
  {
    id: "firewall-auto",
    era: "Accenture",
    title: "Firewall Rule Automation",
    tagline: "Cut manual firewall-rule work by ~40% across enterprise estates.",
    period: "2022 - 2024",
    details: [
      "Wrote scripts to push and validate firewall rule updates across multiple devices.",
      "Reduced manual ticket cycle time and configuration drift.",
      "Improved rule consistency across Telstra Global's hybrid environments.",
    ],
    stack: ["Python", "Shell", "Firewalls", "Automation"],
  },
  {
    id: "malicious-url",
    era: "Undergrad",
    title: "Malicious URL Detection (ML)",
    tagline: "Final-year ML project classifying URLs as safe vs malicious.",
    period: "Nov 2020 - Feb 2021",
    details: [
      "Led a team during lockdown to build, train and evaluate the classifier.",
      "Engineered URL features and benchmarked multiple ML models.",
      "Presented results in multiple seminars to faculty and peers.",
    ],
    stack: ["Python", "Machine Learning", "Team Lead"],
    links: [
      {
        label: "Research Details",
        href: "#research-publications",
      },
    ],
  },
  {
    id: "mask",
    era: "Undergrad",
    title: "COVID Face Mask Detection",
    tagline: "Computer vision classifier on a custom dataset.",
    period: "Mar 2020 - May 2020",
    details: [
      "Built a face-mask detector with a friend-collected custom dataset.",
      "Iterated remotely during the early pandemic.",
    ],
    stack: ["Python", "ML", "Computer Vision"],
  },
  {
    id: "eeg",
    era: "Undergrad",
    title: "Emotion Recognition from EEG Signals",
    tagline: "Internship concept project applying ML to EEG.",
    period: "Dec 2019",
    details: [
      "Explored ML approaches for classifying emotions from EEG signals.",
      "Collaborated with multi-location team and a hackathon.",
    ],
    stack: ["Python", "ML", "Signal Processing"],
  },
];

const researchDetails = [
  "Presented at BIGS 2025 and published for SWDSI 2026.",
  "Built around AI-driven malicious URL detection using deep learning and BERT architecture.",
  "Connects cybersecurity experience with machine learning research and business analytics storytelling.",
  "Shows research writing, model evaluation, and technical presentation experience.",
];

function HuggingFaceMark() {
  return (
    <span className="flex h-5 w-5 items-center justify-center rounded-md bg-amber-100 text-xs font-black text-amber-700">
      HF
    </span>
  );
}

const workLinks = [
  {
    label: "LinkedIn",
    href: LINKEDIN_URL,
    note: "career profile",
    icon: <Linkedin className="h-5 w-5" />,
  },
  {
    label: "GitHub",
    href: GITHUB_URL,
    note: "code projects",
    icon: <Github className="h-5 w-5" />,
  },
  {
    label: "Hugging Face",
    href: HUGGING_FACE_URL,
    note: "AI work",
    icon: <HuggingFaceMark />,
  },
  {
    label: "Research Paper",
    href: "#research-publications",
    note: "BIGS & SWDSI",
    icon: <FileText className="h-5 w-5" />,
  },
];

const eraColors: Record<Project["era"], string> = {
  "UNT - Graduate": "bg-accent/15 text-accent border-accent/30",
  Accenture: "bg-chakra/15 text-chakra border-chakra/30",
  Undergrad: "bg-navy/10 text-navy border-navy/20",
  Independent: "bg-emerald-600/10 text-emerald-700 border-emerald-600/25",
};

export function FeaturedProjectsSection() {
  const [open, setOpen] = useState<string | null>(null);
  const [researchOpen, setResearchOpen] = useState(false);

  return (
    <section id="projects" className="py-24">
      <div className="mx-auto max-w-6xl px-6">
        <div className="flex items-end justify-between flex-wrap gap-4">
          <div>
            <p className="font-display text-accent text-2xl tracking-widest">PROJECTS</p>
            <h2 className="mt-2 font-display text-5xl text-navy">Featured Work</h2>
          </div>
          <p className="text-sm text-muted-foreground max-w-sm">
            Hover or tap a card to read the story behind it.
          </p>
        </div>

        <div className="mt-8 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
          {workLinks.map((link) => (
            <a
              key={link.label}
              href={link.href}
              target={link.href.startsWith("#") ? undefined : "_blank"}
              rel={link.href.startsWith("#") ? undefined : "noreferrer"}
              className="group flex items-center justify-between gap-3 rounded-2xl border border-border bg-card px-4 py-4 text-left transition-all hover:border-accent/45 hover:bg-accent/10 hover:shadow-lg hover:shadow-accent/10"
            >
              <span className="flex items-center gap-3">
                <span className="flex h-10 w-10 items-center justify-center rounded-xl border border-border bg-background text-navy transition-colors group-hover:border-accent/35 group-hover:text-accent">
                  {link.icon}
                </span>
                <span>
                  <span className="block font-display text-xl leading-none text-navy">{link.label}</span>
                  <span className="mt-1 block text-xs uppercase tracking-[0.14em] text-muted-foreground">
                    {link.note}
                  </span>
                </span>
              </span>
              <ExternalLink className="h-4 w-4 text-muted-foreground transition-colors group-hover:text-accent" />
            </a>
          ))}
        </div>

        <motion.div
          id="research-publications"
          role="button"
          tabIndex={0}
          onClick={() => setResearchOpen((current) => !current)}
          onKeyDown={(event) => {
            if (event.key === "Enter" || event.key === " ") {
              event.preventDefault();
              setResearchOpen((current) => !current);
            }
          }}
          onMouseEnter={() => setResearchOpen(true)}
          onMouseLeave={() => setResearchOpen(false)}
          layout
          className={`group mt-8 cursor-pointer rounded-2xl border bg-card px-6 py-5 shadow-sm transition-all ${
            researchOpen ? "border-accent shadow-xl shadow-accent/10" : "border-accent/25 hover:border-accent/40"
          }`}
        >
          <div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
            <div>
              <p className="font-display text-2xl text-navy">Research Publications</p>
              <p className="mt-1 text-sm text-foreground/75">
                AI-Driven Malicious URL Detection using Deep Learning and BERT Architecture.
              </p>
            </div>
            <span className="inline-flex w-fit rounded-full border border-accent/30 bg-card px-4 py-2 text-xs font-semibold uppercase tracking-[0.16em] text-accent">
              Published at BIGS 2025 & SWDSI 2026
            </span>
          </div>

          <AnimatePresence initial={false}>
            {researchOpen && (
              <motion.div
                key="research-details"
                initial={{ opacity: 0, height: 0 }}
                animate={{ opacity: 1, height: "auto" }}
                exit={{ opacity: 0, height: 0 }}
                transition={{ duration: 0.25 }}
                className="overflow-hidden"
              >
                <ul className="mt-5 grid gap-2 text-sm text-foreground/80 md:grid-cols-2 list-disc list-inside">
                  {researchDetails.map((detail) => (
                    <li key={detail}>{detail}</li>
                  ))}
                </ul>
              </motion.div>
            )}
          </AnimatePresence>
        </motion.div>

        <div className="mt-12 grid sm:grid-cols-2 lg:grid-cols-3 gap-5">
          {projects.map((p) => {
            const isOpen = open === p.id;
            const projectLinks =
              p.links ?? [
                {
                  label: "Request Details",
                  href: `mailto:${CONTACT_EMAIL}?subject=${encodeURIComponent(`Project details: ${p.title}`)}`,
                },
              ];
            return (
              <motion.div
                key={p.id}
                role="button"
                tabIndex={0}
                onClick={() => setOpen(isOpen ? null : p.id)}
                onKeyDown={(event) => {
                  if (event.key === "Enter" || event.key === " ") {
                    event.preventDefault();
                    setOpen(isOpen ? null : p.id);
                  }
                }}
                onMouseEnter={() => setOpen(p.id)}
                onMouseLeave={() => setOpen(null)}
                layout
                className={`group relative text-left rounded-2xl border bg-card p-5 overflow-hidden transition-all ${
                  isOpen ? "border-accent shadow-xl shadow-accent/10" : "border-border hover:border-accent/40"
                }`}
              >
                <div className="flex items-center justify-between gap-2">
                  <span className={`inline-block text-xs uppercase tracking-[0.18em] font-semibold rounded-full border px-2 py-0.5 ${eraColors[p.era]}`}>
                    {p.era}
                  </span>
                  <span className="text-xs text-muted-foreground">{p.period}</span>
                </div>
                <h3 className="mt-3 font-display text-xl text-navy leading-tight">{p.title}</h3>
                <p className="mt-2 text-sm text-foreground/75 tracking-wide">{p.tagline}</p>

                <AnimatePresence initial={false}>
                  {isOpen && (
                    <motion.div
                      key="details"
                      initial={{ opacity: 0, height: 0 }}
                      animate={{ opacity: 1, height: "auto" }}
                      exit={{ opacity: 0, height: 0 }}
                      transition={{ duration: 0.25 }}
                      className="overflow-hidden"
                    >
                      <ul className="mt-4 space-y-2 text-base text-foreground/80 list-disc list-inside tracking-wide leading-relaxed">
                        {p.details.map((d) => (
                          <li key={d}>{d}</li>
                        ))}
                      </ul>
                      <div className="mt-4 flex flex-wrap gap-2">
                        {projectLinks.map((link) => (
                          <a
                            key={link.label}
                            href={link.href}
                            target={link.href.startsWith("#") || link.href.startsWith("mailto:") ? undefined : "_blank"}
                            rel={link.href.startsWith("#") || link.href.startsWith("mailto:") ? undefined : "noreferrer"}
                            onClick={(event) => event.stopPropagation()}
                            className="inline-flex rounded-full border border-navy/20 px-4 py-2 text-xs font-semibold text-navy hover:border-accent hover:text-accent transition-colors"
                          >
                            {link.label}
                          </a>
                        ))}
                      </div>
                    </motion.div>
                  )}
                </AnimatePresence>

                <div className="mt-4 flex flex-wrap gap-1.5">
                  {p.stack.map((s) => (
                    <span key={s} className="rounded-md bg-secondary px-2 py-0.5 text-xs font-medium text-secondary-foreground tracking-wide">
                      {s}
                    </span>
                  ))}
                </div>

                <span className="absolute right-4 bottom-4 text-accent text-xs opacity-0 group-hover:opacity-100 transition-opacity">
                  {isOpen ? "-" : "+"}
                </span>
              </motion.div>
            );
          })}
        </div>
      </div>
    </section>
  );
}