Benjamin Looi
Back to projects
Personal Portfolio (2026)

Personal Portfolio (2026)

January 1, 2026

Overview

My previous portfolio was built in 2021 with React. It served me well, but after five years it no longer matched how I build. The tech was outdated, the content was stale, and the design felt like a template. I wanted the new site to show the way I think now: fast pages, clear writing, proper SEO, and enough polish that a recruiter or client would keep reading.

I rebuilt everything with Next.js 15, TypeScript, and Tailwind CSS. The project also gave me a reason to learn the App Router, server components, and technical SEO by shipping them in a real site instead of reading docs in isolation.

The Animated Background

The background follows your cursor with a radial gradient mask over a dot-grid pattern. I kept the effect quiet so it adds depth without fighting the text.

The implementation uses requestAnimationFrame throttling so the effect is smooth without eating CPU. On mobile, it's disabled entirely since there's no cursor to track, and mobile devices don't need the extra rendering overhead.
Portfolio homepage with hero section, animated background, and navigation

Portfolio homepage with hero section, animated background, and navigation

Making the UI Feel Alive

I wanted the site to respond to interaction without feeling like a demo reel. Each navigation link uses a magnetic hover effect that pulls toward the cursor. The nav bar hides while you scroll down and returns when you scroll up, so the content keeps the focus.

The skills section uses glassmorphism cards with semi-transparent backgrounds and backdrop blur. Each card staggers its entrance animation so the section builds up as you scroll into it. The hover states shift the border color toward the primary accent, giving a subtle glow effect.

Skills and technologies section with glassmorphism cards

Skills and technologies section with glassmorphism cards

Content Architecture with MDX

Blog posts and project pages use MDX, so I can mix Markdown with React components. Project pages get inline images and custom formatting, while the writing still feels like writing instead of JSX maintenance.

The blog includes Giscus comments powered by GitHub Discussions, so readers can leave feedback without me needing to manage a separate comment system or database.

Blog listing page with post cards

Blog listing page with post cards

SEO as a First-Class Feature

I built SEO into the site architecture from day one. Each page has metadata for titles, descriptions, Open Graph, and Twitter cards. The app also generates JSON-LD for Person, WebSite, and Article schemas, plus sitemap.xml, robots.txt, and an RSS feed at /feed.xml.

Each blog post has custom meta descriptions and tags in its frontmatter, so search engines get specific, relevant metadata rather than generic defaults. The blog also gives me a place to publish technical notes like my TailwindCSS v4 agent setup breakdown, which supports topical relevance beyond the project pages themselves.

Project Showcase

The projects section shows cover images, tech stack badges, and links. Each project gets a detailed page where I can explain why I made specific decisions and what changed during the build.

Projects listing page with project cards

Projects listing page with project cards

Performance Optimization

After the initial build, I ran Lighthouse audits and fixed the slow paths. The site reached a 98/100 performance score, and Largest Contentful Paint dropped below 1.2 seconds. The main fixes were:

  • LCP fix: Ensured the hero section's critical content loads without render-blocking resources
  • Font optimization: Limited Poppins to only the weights actually used (400, 500, 600, 700) instead of loading the full family
  • Third-party script deferral: PostHog analytics loads lazily so it doesn't block the initial render
  • Event listener throttling: Scroll and mouse handlers use requestAnimationFrame to prevent layout thrashing

Tech Stack

  • Next.js 15: App Router with server components for fast rendering and SEO
  • TypeScript: Full type safety across the codebase
  • Tailwind CSS: Utility-first styling with a custom dark theme
  • Motion (Framer Motion): Entrance animations, magnetic effects, and the animated background
  • MDX: Rich content authoring for blog posts and project pages
  • PostHog: Privacy-friendly analytics for understanding visitor behavior
  • Giscus: GitHub Discussions-powered comments on blog posts

What I Learned

The App Router changed how I split client and server work. Animations, scroll listeners, and analytics belong on the client. Content, metadata, and structured data belong on the server. Getting that boundary right made the site faster.

I also learned that SEO mostly comes down to boring consistency: structured data, heading hierarchy, meta descriptions, semantic HTML, and performance scores.

Related Projects

web
The Eco Garden Cat Project

The Eco Garden Cat Project

A bilingual cat welfare platform for a real colony in Cambodia, with TNVR tracking, KHQR donations, public ledgers, adoption inquiries, volunteer sign-ups, and an admin CMS.

next.js
typescript
tailwind
supabase
web
Baguette POS

Baguette POS

A restaurant POS for Cambodia with fast order entry, table management, dual-currency payments, availability controls, and reporting.

next.js
typescript
tailwind

Related Writing

UX: Disable or hide button?
ux
ui-design
buttons

Hide controls when users cannot use them. Disable controls when users need to understand that an action exists but is not available yet.