A modern personal portfolio built with Next.js (App Router), TypeScript, and Tailwind CSS v4. It highlights experience, projects, skills, blog articles, and contact information with smooth in-page navigation and theme switching.
- Next.js App Router with static + client components where appropriate
- Responsive fixed header with active section tracking (IntersectionObserver)
- In‑page smooth navigation using a delegated hook that respects the dynamic header height
- Accessible theme toggle (light / dark / system) with semantic tokens
- Glass & layered UI styling using Tailwind v4 + OKLCH color tokens
- Mobile sheet menu with scroll locking and focus management
- Blog listing with tags, dates, and reading time
- Projects & Experience sections using reusable
Cardcomponents - Section accent gradients and subtle reveal animations
| Layer | Tech |
|---|---|
| Framework | Next.js 14 (App Router) |
| Language | TypeScript / React 18 |
| Styling | Tailwind CSS v4, custom OKLCH tokens, utility classes |
| Icons | lucide-react |
| Theming | next-themes + CSS variables |
| UI Primitives | Hand-rolled + Radix-based components (sheet, tooltip, etc.) |
| Content | Local data (lib/*), static assets in public/ |
app/ # Next.js app router pages & routes
api/ # API routes (resume view/download)
layout.tsx # Root layout & ThemeProvider
page.tsx # Landing page sections
components/ # Section components + UI primitives
site-header.tsx # Fixed navigation + theme toggle
theme-toggle.tsx # Accessible theme switch
ui/ # UI primitive components (many unused can be pruned)
hooks/ # Reusable client hooks (e.g. use-toast, use-in-page-nav)
lib/ # Data helpers (blog, resume, utils)
public/ # Images, logos, resume PDF, placeholders
scripts/ # Utility scripts (e.g., extract-pdf-text)
styles/ # Global Tailwind layer and tokens
Install dependencies (pnpm recommended):
pnpm installRun development server:
pnpm devBuild production bundle:
pnpm build
pnpm startNo environment variables are required for the current feature set. If you later add analytics, forms, or external APIs, document them here.
Color design tokens are defined in app/globals.css using OKLCH. Dark mode is handled by next-themes adding the class attribute to <html>. The ThemeToggle uses a radiogroup pattern for accessibility. Canonical site URL lives in lib/site.ts.
- Anchor links are plain
<a href="#fragment">elements. - A delegated hook (
useInPageNav) applies smooth scrolling with header offset, sets focus to the target section (or its heading), and updateslocalStoragewith the last active section. - IntersectionObserver updates the active state and styling as the user scrolls.
- Skip link (
#main-content) provided. - Theme toggle uses proper aria roles and visually hidden labels.
- Focus rings preserved with Tailwind focus-visible utilities.
- Mobile menu traps scroll (body overflow lock) but not focus (content is a sheet, dismissible).
A large set of generic UI primitives (accordion, dialog, dropdown, etc.) exists under components/ui/ but many are currently unused. Duplicated hooks removed:
- Removed:
components/ui/use-mobile.tsx,components/ui/use-toast.ts - Active hook versions remain in
hooks/.
If you want to slim the bundle further, you can delete or archive unused primitives. Consider moving them into components/ui/_unused/ first for safe rollback.
- Blog articles: extend
lib/blog.tsdata or migrate to MDX. - Projects / Experience: modify the relevant arrays inside their section components.
- Resume: replace the PDF under
public/resume/with updated filename (adjust API route if name changes).
scripts/extract-pdf-text.cjs – utility for extracting raw text from the resume PDF (locally, not part of runtime).
- Most sections are static and rendered once; only the header, theme toggle, and nav logic are interactive.
- Avoid importing unused heavy UI primitives in top-level components to keep the client bundle lean.
- Remove or archive unused UI components to reduce repo noise
- Add MDX pipeline for blog detail pages
- Implement & toast usage if notifications become needed
- Add tests for hooks (
useInPageNav,use-toast) and theme logic - Integrate SEO metadata per section or blog post
Personal portfolio source. You may reuse patterns, but review and adjust branding, content, and assets before publishing.
Generated README to reflect current architecture and ongoing cleanup efforts.