Portfolio.mp4
A portfolio website built on Next.js 16 (App Router). Prioritizes raw CSS Modules, custom WebGL shaders, and physics-based animations over UI component libraries.
- Framework: Next.js 16.1.6
- Language: TypeScript 5.9.3
- Rendering: React 19.2.3
- 3D: Three.js (r160+) / React Three Fiber
- Animation: GSAP 3.14 (ScrollTrigger, Draggable)
- Scrolling: Lenis
- i18n: next-intl
- Styling: CSS Modules + CSS Variables
- Email: Resend API
State-driven variable injection system using CSSStyleDeclaration.setProperty.
- State: Maintains a
Paletteobject (foreground, background, accent). - Sync:
useEffecthook writes values to:rooton state change. - Persistence:
localStorage+window.matchMediafallback.
Client-side caching layer for GitHub API.
- Mount: Fetch all repo stars via
Promise.all. - Cache: Store result object
{ data, timestamp }inlocalStorage. - Invalidation: Skip fetch if
Date.now() - timestamp < 86400000.
Global filter state accessible via Context API.
- Producer:
TechStack.tsx(About Section). - Consumer:
TechSearchFilter.tsx(Projects Section). - Action: Clicking an icon updates context -> triggers auto-scroll to Projects -> filters list.
Runtime shader modification via onBeforeCompile.
- Materials:
- Base: MeshStandardMaterial.
- Overlay: LineBasicMaterial (Accent Color).
- Shader Injection:
- Vertex: Pass
vWorldPosition. - Fragment: Calculate distance field against
uFadeRadius. - Logic:
gl_FragColor.a *= smoothstep(start, end, position.y).
- Vertex: Pass
- Clipping:
THREE.Planeconstant updated on scroll frame.
Pure GLSL implementation.
- Vertex Shader: Displaces
position.zusingsin(uTime) + distance(uv, uMouse). - Fragment Shader:
- Grid pattern:
fract(vUv * gridLines). - Glow mask:
1.0 - smoothstep(radius, uv).
- Grid pattern:
- Lenis: Intercepts
wheelevent, applies dampening. - Sync:
gsap.ticker.add((time) => lenis.raf(time))ensures single-frame synchronization.
- Translation:
ScrollTriggertracks containerscroll-> Updatestransform: translateX(). - Interaction:
Draggableon proxy element.onDragupdates Lenis scroll target.
Grid packing algorithm for variable-width items.
- Input: Array of items.
- Logic:
if (remaining >= 3): Output row [span-2, span-2, span-2] OR [span-3, span-3] + [span-2, span-2, span-2].if (remaining == 2): Output row [span-3, span-3].if (remaining == 1): Output row [span-6].
- Environment: API Keys accessed via
process.env(Server Runtime). - Validation: Honeypot field check.
- Response: 200 OK / 400 Bad Request / 500 Internal Error.
# 1. Clone
git clone https://github.com/kbtale/portfolio.git
# 2. Install
npm install
# 3. Environment
echo "RESEND_API_KEY=re_123" > .env
echo "CONTACT_EMAIL=me@example.com" >> .env
# 4. Dev
npm run dev
# 5. Build
npm run build