JK
Projects
JK
>LOADING // LOADING
INITIALIZING VIEW
Built and Designed byJK
JK
>LOADING // PROJECT DETAILS
PARSING ARCHITECTURE, DIAGRAMS & API ENDPOINTS
Back to Projects
Live DemoView on GitHub
Jitin K Portfolio
Completednextjsreacttypescripttailwind

Jitin K Portfolio

A modern, responsive portfolio website built with Next.js 16 (App Router), React 19, TypeScript, and Tailwind CSS v4. Projects and tech stack are driven entirely by typed static data in lib/projects/, rendered as animated cards on the home page and /projects, with server-rendered deep-dive detail pages per slug. Includes an interactive hexagon background, dark/light theming, React Flow architecture diagrams, and a serverless contact API.

Problem & Solution

A portfolio needs to showcase projects with rich technical depth — architecture, tech stack decisions, API design — without a CMS or database. This site solves that by modeling each project as TypeScript constants (card + detail joined by slug), so content stays type-safe, ships with the bundle, and renders on the server with zero runtime data fetching.

Features

  • Interactive hexagon SVG background with pointer tracking (requestAnimationFrame + React.memo)
  • Data-driven project showcase: typed card + detail records joined by slug
  • Dynamic /projects/[slug] server-rendered detail pages with 404 for unknown slugs
  • Project cards with hover effects, status badges, live/GitHub links, and tech icon tooltips
  • Interactive React Flow + Dagre architecture diagrams and ER-style table nodes
  • Expandable folder-tree project structure viewer
  • Dark/light mode with system preference detection
  • Framer Motion stagger/fade-up animations with useReducedMotion support
  • Contact form API with validation, HTML escaping, and Upstash sliding-window rate limiting (5 req/min/IP)
  • Nodemailer delivery via Gmail SMTP (port 465, TLS)
  • SEO: metadata API, OpenGraph/Twitter cards, optimized Google Fonts via next/font
  • Responsive layout, custom animated 404 page, Vercel Web Analytics

Tech Stack

TechnologyVersionPurposeWhy Chosen
Next.js^16.1.6App Router frameworkServer Components, file-based routing, API routes, image optimization
React^19.2.4UI libraryServer Components and concurrent rendering
TypeScript^5Type safetyTyped project content catches slug/data mismatches at compile time
Tailwind CSS^4Utility-first stylingCSS-first config with @theme/oklch tokens, no JS config file
Framer Motion^12AnimationsStagger/fade/hover primitives with useInView and useReducedMotion
@xyflow/react + dagre^12.11.5 / ^0.8.5Architecture diagramsData-driven interactive graphs with automatic layout
Nodemailer^7.0.11Contact email deliverySimple Gmail SMTP transport from a single API route
@upstash/ratelimit + @vercel/kv^2.1.0 / ^3.0.0Distributed rate limitingShared sliding-window counter across serverless instances
Radix UI + shadcn/uiprimitives + copied sourceAccessible UI primitivesAccessible tooltips/labels with full style control via copied components
Vercel—Hosting & analyticsZero-config Next.js deploys, CDN, Web Analytics

Architecture

Browser

Next.js Client

RootLayout: Navbar + Footer + Providers

InteractiveHexagonBg

SVG + rAF

Home: Profile + Projects + Techstack

/projects

ProjectCard grid

/projects/[slug]

Server

lib/projects

typed static data

ReactFlowDiagram + FolderTree

/contact

Client Form

POST /api/contact

Upstash Ratelimit / Memory Map

Nodemailer → Gmail SMTP

Vercel CDN + Analytics

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

App Router Pages

  • Root layout (server): fonts, metadata, Providers, Navbar, Footer, hexagon background
  • Home (server): composes Profile, Recent Projects (first 4), Techstack, About sections
  • /projects (client): stagger-animated grid of all ProjectCards
  • /projects/[slug] (server): joins projects[] + projectDetails[] by slug at request time
  • /about, /contact (client) and styled not-found page

Component Layer

  • components/projects/: Project, ProjectCard, ReactFlowDiagram, FolderTree, MermaidDiagram
  • components/animation/: Framer Motion wrappers (stagger, fade-up, hover glow, border trail)
  • components/pattern/: InteractiveHexagonBg (rAF-optimized SVG grid), CssPattern, AnimatedHero
  • components/ui/: shadcn/ui primitives (Badge, Button, Input, Label, Textarea, Tooltip)
  • components/terminal/: Terminal typing preview component

Data & API Layer

  • lib/projects/*.ts: one file per project exporting ProjectType + ProjectDetailType
  • lib/projects/index.ts: aggregates projects[] and projectDetails[] arrays
  • lib/types.ts: TECH_ICONS registry, PROFILE_DATA, and all content type definitions
  • POST /api/contact: server-side validation, rate limiting, Nodemailer → Gmail SMTP

Project Structure

app
about
, app
contact
api
contact
projects
[slug]
components
animation
navbar
, components
footer
, components
profile
, components
theme
pattern
projects
terminal
ui
lib
projects
types.tsTECH_ICONS, PROFILE_DATA, ProjectType, ProjectDetailType
utils.tscn() classname utility
public

API Endpoints

Portfolio API (port 3000)

MethodRoutePurpose
POST/api/contactValidate contact form input, rate-limit by IP, send email via Gmail SMTP

Key Design Decisions

Static TypeScript Data Instead of CMS

Decision: Store all project content as typed constants in lib/projects/*.ts joined by slug

Why: Type safety, zero runtime fetch cost, no database or CMS dependency

Benefits: Compile-time checks, ships with bundle, server-renderable, free hosting footprint

Trade-offs: Content changes require code changes and redeployment

Server/Client Component Split

Decision: Detail pages and layout are server components; lists, diagrams, and forms are client components

Why: Minimize client JS while keeping interactive features

Benefits: Smaller bundle, faster first paint, SEO-friendly detail pages

Trade-offs: Mental overhead of the serialization boundary

Tailwind CSS v4 CSS-First Config

Decision: Configure theme via @theme directives in globals.css instead of tailwind.config.js

Why: Tailwind v4 removes the JS config in favor of CSS-native tokens

Benefits: One file for design tokens, oklch dark/light variables, simpler setup

Trade-offs: Different from v3 muscle memory

React Flow + Dagre for Diagrams

Decision: Derive architecture diagrams from data (nodes/edges) with Dagre auto-layout

Why: Diagrams stay consistent with content and render interactively

Benefits: No hand-drawn images, zoom/pan, themable, ER table nodes supported

Trade-offs: Client bundle cost on pages that render diagrams

Layered Contact API Protection

Decision: Validate + HTML-escape inputs, then rate-limit via Upstash sliding window with in-memory fallback

Why: Serverless instances don't share memory; shared KV store gives consistent limits

Benefits: XSS-safe output, 5 req/min/IP abuse protection, graceful degradation

Trade-offs: Requires KV env vars for full protection; no CSRF token yet

Gmail SMTP via Nodemailer

Decision: Send contact emails through an existing Gmail account

Why: Simplest delivery path for a personal portfolio with no backend infra

Benefits: One route handler, no third-party email SaaS

Trade-offs: App password rotation, self-email only, SMTP rate limits

Testing

None configured•0 unit tests

What's Tested

    Missing Coverage

    • Unit tests for contact API validation and escapeHtml()
    • Unit tests for slug join logic between projects[] and projectDetails[]
    • Component tests for ProjectCard and detail page sections
    • E2E tests for contact form and project navigation flows
    • CI pipeline with lint, typecheck, and build gates (GitHub Actions)

    Key Challenges

    • Serverless rate limiting — in-memory Map resets on cold start; solved with optional Upstash KV sliding window
    • Server/client component boundary — keeping detail pages as server components while diagrams and forms stay interactive
    • Self-referential content — documenting the portfolio inside the portfolio without circular confusion
    • Theme consistency across SVG icons, React Flow diagrams, and hexagon background in dark/light modes
    • Static data still feeling dynamic — staggering animations and hover states over data-driven cards

    Key Learnings

    • Typed static data as a lightweight alternative to a CMS for content-heavy portfolios
    • App Router server component split reduces client bundle while preserving interactivity
    • Dagre layout with React Flow renders clean architecture diagrams from pure data
    • Defense-in-depth for contact forms: validation, HTML escaping, and layered rate limiting
    • CSS-first Tailwind v4 configuration with oklch tokens simplifies theming