A modern, interactive portfolio website built with Next.js 15, featuring stunning animations, interactive mini games.
π Live Preview β
- Stunning Animations - Smooth, professional animations powered by Framer Motion
- Interactive Background - Dynamic floating elements with parallax effects
- Dark/Light Theme - Seamless theme switching with system preference detection
- Responsive Design - Fully optimized for desktop, tablet, and mobile devices
- Hero - Eye-catching introduction with animated terminal
- About - Professional background and expertise
- Skills - Comprehensive technical skill showcase with interactive effects
- Experience - Detailed work history with unique perspectives
- Projects - Portfolio of featured projects with live demos
- Education - Academic background
- Certifications - Professional certifications
- Contact - Get in touch via integrated form
π£ Easter Eggs: This portfolio contains several delightful easter eggs and interactive surprises. Explore and discover them yourself!
- Framework: Next.js 15.3 with App Router
- Language: TypeScript 5
- Styling: Tailwind CSS 3.4
- Animations: Framer Motion 11.2
- UI Components: Radix UI + shadcn/ui
- Icons: Lucide React, React Icons
- Forms: React Hook Form + Zod
- Theme: next-themes
- Email: Resend
- Backend: Firebase
- Node.js 18.x or higher
- npm or yarn package manager
-
Clone the repository
git clone https://github.com/HakkanShah/Portfolio.git cd Portfolio -
Install dependencies
npm install
-
Set up environment variables
Create a
.env.localfile in the root directory:# π§ Email Service (Resend) RESEND_API_KEY=your_resend_api_key # πΎ Discord Webhook (Visitor Notifications) DISCORD_WEBHOOK_URL=your_discord_webhook_url # π₯ Firebase Configuration (Visitor Counter) NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project_id.firebaseapp.com NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project_id.firebasestorage.app NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=your_measurement_id
-
Run the development server
npm run dev
-
Open your browser
Navigate to http://localhost:9002
The chat assistant is powered by an LLM through Groq, grounded on your own content β it does not make facts up from general knowledge.
- Get an API key at console.groq.com/keys.
- Set a spend limit while you're there. The endpoint is public.
- Add it to
.env.local:GROQ_API_KEY=gsk_... GROQ_MODEL=llama-3.3-70b-versatile # optional override NEXT_PUBLIC_SITE_URL=https://your-domain.com # optional; locks the API to your origin
- Check the model id is still current at console.groq.com/docs/models β Groq retires models fairly often, and
GROQ_MODELlets you swap one without a redeploy.
Without a key the site works normally; the bot just explains that it isn't configured.
Two files control what the bot knows β nothing else:
| File | What goes in it |
|---|---|
src/lib/data.ts |
Structured facts: projects, jobs, skills, education, certifications. These already power the visible site, so editing here updates the page and the bot together. |
src/content/profile.ts |
Everything the site doesn't show: how the bot should sound, what you're available for, opinions, FAQs, off-limits topics. Plain prose. |
Built-in guardrails: the phone number in CONTACT_INFO is filtered out of the bot's context, answers are capped in length so the voice mode stays listenable, and /api/chat rate-limits per IP with a global daily ceiling.
- Create a server (or use an existing one) on Discord.
- Go to Server Settings > Integrations > Webhooks.
- Click New Webhook, give it a name (e.g., "Portfolio Bot"), and copy the Webhook URL.
- Paste it into your
.env.localasDISCORD_WEBHOOK_URL.
- Go to Firebase Console and create a new project.
- Navigate to Firestore Database and create a database (Start in production mode).
- Go to Project Settings > General > Your apps > Web app (</> icon).
- Register the app and copy the
firebaseConfigobject values to your.env.local. - Important: Set Firestore Rules to allow read/write for the counter:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /site_stats/visitors { allow read, write: if true; } } }
Track where your visitors are coming from by adding a ?ref= parameter to your URL.
- LinkedIn:
your-site.com/?ref=linkedin - Twitter:
your-site.com/?ref=twitter - Instagram:
your-site.com/?ref=instagram
The Discord notification will show "π Source: linkedin".
# Development server (with Turbopack)
npm run dev
# Build for production
npm run build
# Start production server
npm start
# Lint code
npm run lint
# Type checking
npm run typecheckportfolio/
βββ src/
β βββ app/ # Next.js app directory
β β βββ api/chat/ # Groq-backed assistant endpoint
β β βββ globals.css # Global styles and animations
β β βββ layout.tsx # Root layout with theme provider
β β βββ page.tsx # Home page
β β βββ sitemap.ts # Dynamic sitemap generation
β βββ components/ # React components
β β βββ assistant/ # Hakkan Bot chat UI + 3D bot
β β βββ games/ # Interactive mini-games
β β βββ ui/ # shadcn/ui components
β β βββ hero-section.tsx
β β βββ about-section.tsx
β β βββ skills-section.tsx
β β βββ ...
β βββ content/ # Prose the site doesn't render
β β βββ profile.ts # What the bot knows beyond data.ts β edit me
β βββ hooks/ # Custom React hooks
β βββ lib/ # Utilities and data
β βββ assistant/ # Bot: prompt building, API client, voice
β βββ data.ts # Portfolio content data β edit me
β βββ sound.ts # Audio utilities
β βββ utils.ts # Helper functions
βββ public/ # Static assets
βββ .gitignore
βββ next.config.ts # Next.js configuration
βββ tailwind.config.ts # Tailwind configuration
βββ tsconfig.json # TypeScript configuration
βββ package.json
Edit src/lib/data.ts to customize:
- Personal information
- Skills and expertise
- Work experience
- Projects
- Education
- Certifications
This is also what the AI assistant reads, so the site and the bot can never drift apart. For the bot's tone and anything the site doesn't display, edit src/content/profile.ts.
Update tailwind.config.ts to change color scheme:
theme: {
extend: {
colors: {
// Customize your colors here
}
}
}Adjust animation settings in src/app/globals.css:
@keyframes your-animation {
/* Custom animation keyframes */
}Set these in Vercel β Project β Settings β Environment Variables (Production, Preview and Development), and mirror them in a local .env.local. See .env.example.
| Variable | Required | Notes |
|---|---|---|
GROQ_API_KEY |
Yes, for the bot | Without it the site works fine and the bot says it isn't configured. Server-only β never prefix with NEXT_PUBLIC_. |
GROQ_MODEL |
No | Overrides the default model. Change here instead of redeploying code when Groq retires a model. |
NEXT_PUBLIC_SITE_URL |
Recommended | Locks /api/chat to your own origin. www., *.vercel.app previews and localhost are allowed automatically. Leave unset and the check is skipped. Inlined at build time, so changing it needs a redeploy. |
RESEND_API_KEY |
For the contact form | |
DISCORD_WEBHOOK_URL |
For visitor pings | |
NEXT_PUBLIC_FIREBASE_* |
For the visitor counter |
npm run typecheck # must be clean β type errors now fail the build
npm run build-
GROQ_API_KEYset in Vercel, and a spend limit set in the Groq console β/api/chatis a public endpoint that costs money per call - Model id in
GROQ_MODELstill listed at console.groq.com/docs/models -
src/content/profile.tshas noTODOleft that you care about - Ask the deployed bot "where do you work now" β it must say Persist
- Push your code to GitHub
- Import your repository on Vercel
- Add the environment variables above
- Deploy!
Note:
/api/chatruns on the Node runtime withmaxDuration = 15sand aborts the upstream call at 8s. On the Vercel Hobby plan that sits inside the function limit.
- Push your code to GitHub
- Connect your repository on Netlify
- Build command:
npm run build - Publish directory:
.next - Deploy!
# Build the project
npm run build
# Deploy to Firebase
firebase deployThis project is open source and available under the MIT License.
- Portfolio: hakkan.is-a.dev
- LinkedIn: Hakkan
- GitHub: @HakkanShah
- Email: hakkanparbej@gamil.com
- Framer Motion for the incredible animation library
- shadcn/ui for the beautiful UI components
- Lucide for the icon set
- Vercel for Next.js and hosting platform
Built with β€οΈ by Hakkan Shah
β Star this repo if you find it helpful!