This portfolio is itself a demonstration of modern full-stack engineering. Below is a breakdown of every architectural decision — why it was made, what it replaced, and how it fits together. Useful context for anyone evaluating the technical depth behind the work.
Tech Stack
| Layer | Technology | Why |
|---|---|---|
| Framework | Next.js 16 (App Router) | SSR, API routes for AI chat, next/image optimization |
| Language | TypeScript | Type-safe data layer eliminates an entire class of runtime errors |
| Styles | Tailwind CSS v4 | CSS-first design token system replaces 4,882 lines of legacy CSS |
| Animations | Framer Motion | Replaces Swiper.js + jQuery for carousels, modals, and page transitions |
| Content | MDX via next-mdx-remote | Author project case studies and blog posts as Markdown files |
| AI | Groq API (server-side only) | llama-3.3-70b-versatile; API key stays in Vercel env vars, never in browser |
| Icons | Lucide React | Tree-shakeable SVG components replace the 570 KB Font Awesome bundle |
| Deployment | Vercel via GitHub Actions | API routes require a live server; Vercel is free for personal projects |
| Resend | Replaces broken PHP mailer; server-side only, no secrets in frontend |
AI Assistant Architecture
The chat widget connects to a Next.js API route (/api/chat) that calls the Groq API server-side. The API key is stored in Vercel environment variables and never shipped to the browser. If no key is configured, the route returns mock responses automatically — the UI always works.
Browser → ChatWidget.tsx (client component)
→ POST /api/chat (Next.js API route)
→ Groq SDK (server-side only)
→ llama-3.3-70b-versatile
← 256-token response
← JSON { reply: string }
Browser ← renders message
No RAG, no embeddings. The system prompt is assembled from src/data/ai-context.ts — plain text strings covering skills, experience, projects, and contact info. Keeping the context small and structured produces more accurate, concise answers than a full-document retrieval approach for a portfolio use case.
Content System
All content lives in TypeScript data files and MDX files — never hardcoded in components. Adding a new project means creating one .mdx file and one entry in src/data/projects.ts. No component changes required.
| File | Purpose |
|---|---|
src/data/projects.ts | Project[] — listing metadata, metrics, links |
src/data/experience.ts | Experience[] — all 6 work entries |
src/data/education.ts | EducationEntry[] — institutions + modal content |
src/data/skills.ts | SkillCategory[] — 8 skill groups |
src/content/projects/*.mdx | Full case study prose for each project |
src/content/blog/*.mdx | Blog posts with frontmatter metadata |
Build Phases
01 — Scaffolding: Next.js project, Tailwind design tokens, CRT globals.css, asset migration.
02 — Core Sections: One-page scroll (8 sections), dot pagination, all section components.
03 — Content System: MDX for project case studies and blog posts, /projects + /blog routes.
04 — API Layer: Groq AI chat route (mock + real), Resend contact form route.
05 — Polish: WCAG AA audit, Lighthouse optimization, SEO metadata, sitemap.
Performance & Accessibility
next/imagefor automatic WebP conversion and responsive srcsets- CSS-only CRT scanlines — no JavaScript overhead
- Dynamic import for
ChatWidget— excluded from the SSR bundle generateStaticParamsfor all MDX routes — pre-rendered at build time- WCAG AA: focus rings on all interactive elements, ARIA labels, alt text
- Zero border-radius via CSS global rule — no per-component overrides needed

