A jaw-dropping developer portfolio packed with interactive 3D animations, buttery smooth transitions, and a space-themed aesthetic. Not your average portfolio template! This one has a fully interactive 3D keyboard where each keycap is a skill.
Free to use! This portfolio is open source. If you use it, a credit/link back would be really appreciated 🙏
- Interactive 3D Keyboard — Custom Spline keyboard where each keycap represents a skill, revealing titles and descriptions on hover/press
- Buttery Animations — GSAP + Framer Motion powered scroll, hover, and reveal animations
- Space Theme — Floating particles on a dark canvas for a cosmic vibe
- Light & Dark Mode — Full theme support with cheeky disclaimer toasts
- Responsive — Works across all screen sizes
- Contact Form — Email delivery via Resend
- Analytics (optional) — Umami analytics integration
| Layer | Technologies |
|---|---|
| Framework | Next.js 14, React 18, TypeScript |
| Styling | Tailwind CSS, Shadcn UI, Aceternity UI |
| Animation | GSAP, Framer Motion |
| 3D | Spline Runtime |
| Resend | |
| Misc | Lenis (smooth scroll), Zod, next-themes |
- Node.js (v18+)
- pnpm (recommended), npm, or yarn
-
Clone the repository:
git clone https://github.com/Naresh-Khatri/3d-portfolio.git cd 3d-portfolio -
Install dependencies:
pnpm install
-
Set up environment variables:
Copy
.env.exampleto.env.localand fill in the values:cp .env.example .env.local
Variable Required Description RESEND_API_KEYYes API key from Resend for the contact form NEXT_PUBLIC_WS_URLNo WebSocket server URL for realtime features (cursors, chat, presence) UMAMI_DOMAINNo Umami analytics script URL UMAMI_SITE_IDNo Umami website ID -
Run the development server:
pnpm dev
-
Open http://localhost:3000 and see the magic ✨
All personal info is centralized in src/data/config.ts. Edit this single file to rebrand the portfolio:
const config = {
title: "Your Name | Your Title",
description: {
long: "Your long description for SEO...",
short: "Your short description...",
},
keywords: ["your", "keywords"],
author: "Your Name",
email: "you@example.com",
site: "https://yoursite.com",
// GitHub stars button in the header
githubUsername: "your-github-username",
githubRepo: "your-repo-name",
social: {
twitter: "https://x.com/you",
linkedin: "https://linkedin.com/in/you",
instagram: "https://instagram.com/you",
facebook: "https://facebook.com/you",
github: "https://github.com/you",
},
};Other files you'll want to customize:
| File | What to change |
|---|---|
src/data/projects.tsx |
Your projects, screenshots, descriptions, and tech stacks |
src/data/constants.ts |
Skills list (name, description, icon) and work experience |
public/assets/ |
Your images, OG image, and project screenshots |
The 3D keyboard keycaps are baked into a Spline file. To update the skills displayed on the keyboard:
- Import the
public/assets/skills-keyboard.splinefile into Spline - Unhide the keycap objects you want to edit
- Update the logo images on each keycap to your new skill icons
- Rename each keycap object to match the skill's
namefield insrc/data/constants.ts(e.g.js,react,docker) - Hide all keycap objects again
- Export the scene and overwrite
public/assets/skills-keyboard.spline
After updating the Spline file, make sure src/data/constants.ts has matching entries for every skill on the keyboard:
// Each keycap object name in Spline must match a key in SKILLS
export const SKILLS: Record<SkillNames, Skill> = {
js: { name: "js", label: "JavaScript", shortDescription: "...", ... },
react: { name: "react", label: "React", shortDescription: "...", ... },
// ... add/remove entries to match your keyboard
};The SkillNames enum, SKILLS record, and the Spline keycap names must all stay in sync for the keyboard interactions to work correctly.
The portfolio supports optional realtime features powered by a separate backend API:
- 🖱️ Live cursors — See other visitors' cursors in realtime
- 👥 Online presence — Shows who's currently on the site
- 💬 Chat — Live chat between visitors
These features activate automatically when the NEXT_PUBLIC_WS_URL environment variable is set. Without it, the portfolio works perfectly fine as a static site — no realtime features, no backend dependency.
Note
The backend API is not open source. This is intentional! Too many people have cloned the portfolio and claimed they built it from scratch. The realtime server stays private to keep the live experience unique make make it standout.
This site is deployed on Vercel. To deploy your own:
- Push your code to a GitHub repository
- Connect the repository to Vercel
- Add your environment variables in the Vercel dashboard
- Vercel handles the rest — automatic deployments on every push
If you'd like to contribute or suggest improvements, feel free to open an issue or submit a pull request. All contributions are welcome!
This project is open source and available under the MIT License.
If you use this portfolio, a credit or link back to the original repo would be much appreciated ❤️
