A production-ready, accessible, responsive developer portfolio built with:
- Next.js 14 (App Router)
- TypeScript (strict mode)
- Tailwind CSS (custom design system)
- Framer Motion (scroll animations)
- next-themes (dark/light mode)
Inspired by and merging the best ideas from top GitHub portfolio repositories:
brittanychiang/v4— clean nav, side layout philosophycobiwave/simplefolio— section structure & minimal claritysoumyajit4419/Portfolio— React patterns & component architecturehrishikeshpaul/portfolio-template— timeline UXnicktarnold/devfolio— filter tabs on projects
# 1. Install dependencies
npm install
# 2. Start dev server
npm run dev
# 3. Open http://localhost:3000portfolio/
├── app/
│ ├── layout.tsx # Root layout + metadata + ThemeProvider
│ └── page.tsx # Main page — assembles all sections
├── components/
│ ├── layout/
│ │ ├── Navbar.tsx # Sticky nav, active link, theme toggle, mobile drawer
│ │ └── Footer.tsx # Social links, credit line
│ ├── sections/
│ │ ├── Hero.tsx # Typewriter, CTAs, availability badge
│ │ ├── About.tsx # Bio + animated stats grid
│ │ ├── Experience.tsx # Accordion timeline
│ │ ├── Projects.tsx # Filterable card grid
│ │ ├── Skills.tsx # Categorised skill chips
│ │ └── Contact.tsx # Validated form + social links
│ └── ui/
│ ├── ScrollProgress.tsx # Thin accent bar at top
│ ├── RevealObserver.tsx # IntersectionObserver for .reveal elements
│ ├── SocialIcon.tsx # Typed icon switcher
│ └── Tag.tsx # Tech chip
├── lib/
│ ├── data.ts # ✏️ ALL your content lives here — edit this!
│ └── utils.ts # cn() helper
├── styles/
│ └── globals.css # CSS variables, animations, utility classes
├── types/
│ └── index.ts # Shared TypeScript interfaces
├── public/
│ └── resume.pdf # Add your CV here
├── tailwind.config.ts
├── tsconfig.json
└── next.config.ts
All content is in one file: lib/data.ts
Edit:
personalInfo— name, title, bio, email, socialsexperiences— work historyprojects— your projectsskillCategories— your tech stackstats— headline numbers
Design tokens (colours, fonts) are in styles/globals.css as CSS variables.
npm i -g vercel
vercelnpm run build
npm start- WCAG AA compliant colour contrast
- All interactive elements keyboard-navigable
- ARIA labels on icons, form fields, and sections
aria-liveregions for dynamic content (typewriter, form state)- Focus rings visible in both light and dark modes
Replace the await new Promise(...) mock in Contact.tsx with a real endpoint:
// Example: Formspree
const res = await fetch("https://formspree.io/f/YOUR_ID", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(form),
});
if (!res.ok) throw new Error("Failed");Other options: Resend, EmailJS, AWS SES, your own API route at app/api/contact/route.ts.