Portfolio Template
A reusable Next.js 13 portfolio template — App Router, TypeScript, Framer Motion animations, and secure contact form via React Email + Resend. Used by me at whyian.dev.
- Type
- Web
- Role
- Solo
- Status
- Archived
- Tech
- Next.js 13 TypeScript Tailwind CSS Framer Motion React Email Resend
- Started
- Sep 2023
Overview
A fully responsive Next.js 13 portfolio template built around the then-new App Router, with TypeScript from day one, Framer Motion animations, and a working contact form wired to Resend. I use it at whyian.dev. The repo is public so anyone can fork it as a starting point for their own personal site.
Features
- Latest Next.js 13 — App Router, Server Actions, and the split between Client and Server components built in from the start.
- TypeScript end-to-end — every component, hook, and API route is typed, so refactoring is fearless.
- Tailwind CSS + light/dark mode — clean responsive UI that adapts to system preference.
- Framer Motion — smooth scroll-driven and hover animations for section transitions, card reveals, and subtle micro-interactions.
- Secure email via React Email + Resend — the contact form composes an email template with React.Email, sends it through Resend, and validates input server-side so the form can’t be abused.
- Custom React hooks — small utility hooks for scroll position, section-in-view detection, and active-section tracking.
- Performance — Lighthouse 95+, average load time under 100ms on the deployed version.
- 100% responsive — works cleanly down to 360px mobile.
Stack
- Framework: Next.js 13 with App Router
- Language: TypeScript 5
- Styling: Tailwind CSS with a custom design system
- Animation: Framer Motion
- Email: React.Email for templating, Resend for delivery
- Hosting: Vercel
Notable bits
- Server Actions for the contact form — no separate API route, the form just posts to a server action that validates and calls Resend. Cleaner code, one less abstraction layer.
- Scroll-driven section tracking — a custom
useActiveSectionhook observes scroll position and highlights the current section in the nav, using IntersectionObserver so it’s cheap. - Dark mode as a design constraint, not an afterthought — every color in the palette was chosen to look right in both themes, not just flipped via an inverted filter.