A modern, feature-rich developer portfolio built with Next.js 16, React 19, and TypeScript. Showcase your projects, write about your journey, and connect real-time integrations with GitHub, Spotify, Codewars, WakaTime, and more—all powered by AI chat and a beautiful, responsive design.
Live demo: https://zidvsd.site/
- What You Get
- Quick Start
- Configuration
- Project Structure
- Core Features & Integrations
- Admin Dashboard
- Customization
- API Routes
- Database
- Development
- Troubleshooting
- Contributing
- License
Real-time Integrations — GitHub, Spotify, Codewars, WakaTime
AI Chat Assistant — Google Gemini-powered visitor interactions
Blog System — Markdown support with admin dashboard
Comments — Global and blog-specific comment threads
Authentication — Better Auth with session management
Dark/Light Theme — Seamless theme switching
Mobile-First Design — Fully responsive and accessible
Email Integration — Contact form with Resend
Deployment Ready — Optimized for Vercel or any Node.js host
- Next.js 16 App Router with streaming and optimized performance
- React 19 Server & Client Components
- TypeScript for type safety across the codebase
- Tailwind CSS + shadcn/ui for beautiful, accessible components
- Mongoose + MongoDB for reliable data persistence
- ESLint + Prettier for consistent code quality
- GitHub — Fetch repositories, contribution stats, and profile activity
- Spotify — Display currently playing tracks and personalized playlists
- Codewars — Showcase coding challenge progress and rankings
- WakaTime — Visualize coding activity breakdown by language
- Google Gemini — AI-powered chat assistant for visitor interactions
- Resend — Reliable email delivery for contact form submissions
- Projects — GitHub-synced projects with featured showcase and detail pages
- Blog — Markdown-powered blog with filtering, search, and admin dashboard
- Dashboard — Real-time stats and integrations widget gallery
- Achievements — Track milestones, certifications, and accomplishments
- Contact — Form with email validation and AI-assisted responses
- About — Personalized profile with skills, experience, and status
- Dark/Light theme support with persistent preference
- Mobile-first responsive design
- Smooth page transitions and animations with Framer Motion
- Skeleton loaders for perceived performance
- Toast notifications (Sonner)
- Image carousels with keyboard navigation (Embla)
Before you begin, ensure you have:
- Node.js 18+ and npm/yarn/pnpm
- MongoDB Atlas account (free tier available) OR local MongoDB instance via Docker
- API keys for the integrations you want to use (optional for local development)
-
Clone and install
git clone https://github.com/yourusername/portfolio-v2.git cd portfolio-v2 npm install -
Set up environment variables
# Copy the template cp .env.example .env.local # Edit with your API keys
-
Start the development server
npm run dev
Open http://localhost:3000 in your browser. The app auto-reloads on file changes thanks to Turbopack.
Create a .env.local file in the project root. Here's a complete template:
# Database
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/portfolio
# GitHub (optional - for project fetching)
NEXT_PUBLIC_GITHUB_USERNAME=your-username
GITHUB_API_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
# Spotify (optional - for music integration)
NEXT_PUBLIC_SPOTIFY_CLIENT_ID=your_client_id
SPOTIFY_CLIENT_SECRET=your_client_secret
SPOTIFY_REFRESH_TOKEN=your_refresh_token
# Google Gemini (optional - for AI chat)
GEMINI_API_KEY=your_gemini_api_key
# WakaTime (optional - for activity stats)
WAKATIME_API_KEY=your_wakatime_api_key
# Codewars (optional - for coding challenges)
CODEWARS_USERNAME=your_codewars_username
# Email (Resend - for contact form)
RESEND_API_KEY=your_resend_api_key
# App Configuration
NEXT_PUBLIC_APP_URL=http://localhost:3000| Service | Link | Required? |
|---|---|---|
| GitHub | Create Personal Access Token | No |
| Spotify | Developer Dashboard | No |
| Google Gemini | Create API Key | No |
| WakaTime | Settings → API Key | No |
| Codewars | Public API | No |
| Resend | Get API Key | Only for contact form |
| MongoDB | Create Atlas Cluster | Yes |
Note: All integrations except MongoDB are optional. The portfolio works great with just MongoDB for local development.
npm run dev # Start dev server with Turbopack (instant HMR)
npm run build # Build for production
npm start # Run production server locally
npm run typecheck # Full TypeScript type checking
npm run lint # ESLint + Next.js lint check
npm run format # Prettier code formattingportfolio-v2/
├── app/ # Next.js App Router (server-rendered)
│ ├── page.tsx # Home page with hero & projects
│ ├── layout.tsx # Root layout & providers
│ ├── globals.css # Global styles & CSS variables
│ ├── (auth)/ # Auth group
│ │ ├── login/page.tsx
│ │ └── signup/page.tsx
│ ├── (admin)/ # Protected admin routes
│ │ └── studio/
│ ├── about/page.tsx # About section
│ ├── achievements/page.tsx # Achievements showcase
│ ├── projects/ # Projects section
│ │ ├── page.tsx
│ │ └── [projectId]/page.tsx
│ ├── blog/ # Blog section
│ │ ├── page.tsx
│ │ └── [slug]/page.tsx
│ ├── dashboard/page.tsx # Integrations dashboard
│ ├── contact/page.tsx # Contact form
│ └── api/ # API routes
│ ├── auth/route.ts
│ ├── chat/route.ts # AI chat endpoint (Gemini)
│ ├── contact/route.ts # Email submission (Resend)
│ └── blog/route.ts
│
├── components/ # React components (UI & features)
│ ├── layout/
│ │ ├── MainLayout.tsx
│ │ ├── Sidebar.tsx
│ │ └── MobileMenuDrawer.tsx
│ ├── dashboard/ # Integration cards
│ │ ├── GitHubCard.tsx
│ │ ├── SpotifyCard.tsx
│ │ ├── CodewarsCard.tsx
│ │ ├── WakaTimeCard.tsx
│ │ └── ...
│ ├── blog/
│ │ ├── BlogCard.tsx
│ │ ├── BlogList.tsx
│ │ ├── BlogSinglePage.tsx
│ │ └── BlogFilterBar.tsx
│ ├── forms/
│ │ ├── LoginForm.tsx
│ │ ├── SignUpForm.tsx
│ │ ├── ContactForm.tsx
│ │ └── BlogForm.tsx
│ ├── ui/ # shadcn/ui & custom components
│ ├── themes/ # Theme provider
│ ├── motion/ # Animation wrappers
│ │ ├── MotionWrapper.tsx
│ │ ├── StaggerWrapper.tsx
│ │ └── InView.tsx
│ ├── skeleton/ # Loading skeletons
│ └── sections/
│ ├── home/
│ ├── blog/
│ ├── projects/
│ └── achievements/
│
├── lib/ # Utilities & configuration
│ ├── services/ # External API integrations
│ │ ├── github.ts # GitHub API
│ │ ├── spotify.ts # Spotify API
│ │ ├── codewars.ts # Codewars API
│ │ ├── wakatime.ts # WakaTime API
│ │ ├── resend.ts # Email service
│ │ ├── queries.ts # Database queries
│ │ └── gemini.ts # Google Gemini AI
│ ├── constants/
│ │ ├── projects-config.ts # Featured projects
│ │ └── tech-data.ts # Technology metadata
│ ├── types/ # TypeScript definitions
│ │ └── index.ts
│ ├── schemas/ # Zod validation schemas
│ ├── db.ts # MongoDB connection
│ ├── auth.ts # Authentication setup (Better Auth)
│ ├── utils.ts # Utility functions
│ └── markdown-parser.ts # Markdown → HTML conversion
│
├── models/ # Mongoose schemas
│ ├── Profile.ts # User profile
│ ├── Blogs.ts # Blog posts
│ ├── Achievements.ts # Achievements
│ └── Experiences.ts # Work experience
│
├── hooks/ # Custom React hooks
│ └── useBlogFilters.ts
│
├── public/ # Static assets
│ ├── images/
│ ├── icons/
│ └── ...
│
├── package.json
├── tsconfig.json
├── next.config.mjs
├── tailwind.config.ts
└── postcss.config.mjs
This portfolio uses Better Auth for secure authentication with MongoDB integration:
- Session Management — Automatic session handling with secure tokens
- User Management — Sign up, login, and profile management
- Bearer Token Support — API authentication for protected routes
- Protected Routes — Admin sections require authentication
// app/(admin)/studio/page.tsx
import { auth } from "@/lib/auth/auth"
export default async function AdminPage() {
const session = await auth.api.getSession()
if (!session) {
redirect("/login")
}
return <AdminDashboard />
}Automatically fetch and display your repositories with real-time data:
// app/projects/page.tsx
import { getProjects } from "@/lib/services/github"
export default async function ProjectsPage() {
const projects = await getProjects()
return <ProjectList projects={projects} />
}Configure featured projects in lib/constants/projects-config.ts:
export const MY_PROJECTS = [
{
name: "Portfolio v2",
slug: "portfolio-v2",
deployUrl: "https://portfolio.dev",
image: "/images/projects/portfolio-v2.png",
isFeatured: true,
},
]Features:
- Auto-synced repository list
- Contribution graph visualization
- Profile stats (followers, stars, etc.)
Display your music taste in real-time:
// components/dashboard/SpotifyCard.tsx
import { SpotifyPlayingCard } from "@/components/dashboard/SpotifyPlayingCard"
import { SpotifyPlaylistCarousel } from "@/components/dashboard/SpotifyPlaylistCarousel"
export default function SpotifySection() {
return (
<>
<SpotifyPlayingCard />
<SpotifyPlaylistCarousel />
</>
)
}Setup:
- Create a Spotify Developer App
- Get Client ID, Client Secret, and Refresh Token
- Add to
.env.local
Google Gemini powers an intelligent chat assistant on your portfolio:
// POST /api/chat
const response = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: "Tell me about your projects" }),
})
const { reply } = await response.json()The AI uses a personalized system prompt to answer questions about your portfolio, projects, and experience.
Track your coding activity:
- WakaTime — Languages, projects, and time spent coding
- Codewars — Challenge rating, completed katas, language leaderboards
// components/dashboard/WakaTimeCard.tsx & CodewarsCard.tsx
<WakaTimeWrapper />
<CodewarsCardWrapper />Submit contact requests with automatic email delivery via Resend:
// POST /api/contact
{
"name": "John Doe",
"email": "john@example.com",
"subject": "Project Inquiry",
"message": "I'd like to discuss..."
}Responses are validated with Zod and sent to your email instantly.
Access the protected admin studio at /admin/studio to manage your portfolio content:
- Blog Management — Create, edit, and publish blog posts with Markdown support
- View Submissions — Review contact form submissions and comments
- Profile Updates — Manage your profile information and settings
- Integration Status — Monitor connected services and API status
The admin dashboard requires authentication via Better Auth. Ensure you're logged in to access restricted features.
Edit your profile information via MongoDB. The profile model includes:
// models/Profile.ts
{
name: "Your Name",
headline: "Full Stack Developer",
location: "San Francisco, CA",
workStatus: "Open to opportunities",
bio: "I build web apps and love open source",
socials: {
github: "https://github.com/yourusername",
linkedin: "https://linkedin.com/in/yourprofile",
twitter: "https://twitter.com/yourhandle",
email: "you@example.com"
},
skills: ["React", "Next.js", "TypeScript", "MongoDB", "Tailwind CSS"],
}Modify Tailwind configuration in tailwind.config.ts:
export default {
theme: {
extend: {
colors: {
primary: "#your-color",
accent: "#highlight-color",
},
fontFamily: {
sans: ["var(--font-sans)"],
mono: ["var(--font-mono)"],
},
},
},
}Blog posts are stored in MongoDB. Create a new blog via:
- Admin dashboard at
/admin/studio(or manually via MongoDB) - Use the BlogForm component
- Write in Markdown with syntax highlighting support
// Example blog document structure
{
title: "Getting Started with Next.js 16",
slug: "getting-started-nextjs-16",
content: "# Next.js 16\n\n...",
category: "Web Development",
featured: true,
createdAt: Date.now(),
}Create new integration cards by following the component pattern:
// components/dashboard/YourCard.tsx
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
export function YourIntegrationCard() {
const [data, setData] = useState(null)
useEffect(() => {
// Fetch data from API
}, [])
return (
<Card className="backdrop-blur-sm">
<CardHeader>
<CardTitle>Your Integration</CardTitle>
</CardHeader>
<CardContent>
{/* Render your data */}
</CardContent>
</Card>
)
}Then import and use in app/dashboard/page.tsx.
All API routes enforce request validation with Zod and return JSON responses.
Fetch or create comments with support for global and blog-specific comments.
GET Request:
# Get global comments
GET /api/comments?type=global
# Get comments for a specific blog post
GET /api/comments?type=blog&blogId=<blogId>GET Response:
{
"comments": [
{
"_id": "...",
"content": "Great article!",
"author": {
"name": "John Doe",
"email": "john@example.com"
},
"type": "blog",
"createdAt": "2024-01-15T10:30:00Z"
}
]
}POST Request:
{
"content": "This is a comment",
"type": "blog",
"blogId": "<blogId>"
}POST Response:
{
"success": true,
"comment": {
"_id": "...",
"content": "This is a comment",
"type": "blog",
"createdAt": "2024-01-15T10:30:00Z"
}
}Rate Limiting: Comments are rate-limited to 30 requests per minute per IP address.
Send a message to the AI chat assistant powered by Google Gemini.
Request:
{
"message": "What technologies do you use?"
}Response:
{
"reply": "I use Next.js, React, TypeScript, MongoDB, and Tailwind CSS..."
}Error Response:
{ "error": "Invalid message" }Submit a contact form with automatic email delivery.
Request:
{
"name": "Jane Smith",
"email": "jane@example.com",
"subject": "Project Inquiry",
"message": "I'd like to collaborate on..."
}Response:
{ "success": true, "message": "Email sent successfully" }Fetch or create blog posts (protected with authentication).
GET Response:
{
"blogs": [
{
"_id": "...",
"title": "My First Blog",
"slug": "my-first-blog",
"content": "...",
"createdAt": "2024-01-15T10:30:00Z"
}
]
}This project uses MongoDB with Mongoose for schema validation and queries.
Manages user accounts, authentication, and sessions via Better Auth.
// models/User.ts
{
email: string,
name: string,
password: string (hashed),
emailVerified: boolean,
image?: string,
createdAt: Date,
updatedAt: Date,
}Stores user profile information and settings.
Blog post and global comments with user references.
// models/Comments.ts
{
content: string,
blogPost: ObjectId (optional),
author: ObjectId (User reference),
type: "global" | "blog",
createdAt: Date,
}Blog posts with markdown content, categories, and metadata.
Milestones, certifications, and accomplishments.
Work history and professional experience.
Option 1: Docker (Recommended)
docker run -d \
-p 27017:27017 \
--name mongodb \
mongo:latestOption 2: MongoDB Atlas (Free)
- Create account at mongodb.com/atlas
- Create a free M0 cluster
- Get connection string and add to
.env.local
Create initial data by connecting to MongoDB:
import { connectDB } from "@/lib/db"
import Profile from "@/models/Profile"
async function seed() {
await connectDB()
const profile = await Profile.create({
name: "Your Name",
headline: "Full Stack Developer",
// ... other fields
})
console.log("Profile created:", profile)
}
seed()This project uses modern tooling for consistency and reliability:
# Type checking
npm run typecheck
# Linting
npm run lint
# Code formatting (auto-fix)
npm run format
# All checks before commit
npm run typecheck && npm run lint && npm run format- Server Components by Default — Use Server Components in App Router for data fetching
- TypeScript Everywhere — Full type coverage, no
anytypes - Component Separation — Isolate client-side interactivity with
"use client" - Utility Functions — Keep logic in
lib/for reusability - API Organization — Group related API routes by feature
Vercel is the official Next.js platform with zero-config deployments:
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Set environment variables in Vercel dashboardThe portfolio is pre-optimized for speed:
- Server Components — Reduces client-side JavaScript
- Image Optimization — Next.js Image component with lazy loading
- Dynamic Imports — Code splitting for better initial load time
- Database Caching — Mongoose query optimization
- CDN Integration — Static assets served globally on Vercel
- Turbopack — 5-10x faster hot module replacement during development
- Environment Variables — Never commit
.env.localto version control - API Route Protection — Use authentication middleware for sensitive endpoints
- Rate Limiting — Comments API includes built-in rate limiting (30 req/min)
- CORS — Configured for cross-origin requests
- Input Validation — All user inputs validated with Zod schemas
- Token Refresh — Automatic token rotation for external services
This means the path alias isn't configured correctly. Ensure your tsconfig.json has:
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}- Ensure
MONGODB_URIis set in.env.local - Check that your MongoDB cluster has network access enabled
- Clear browser cookies and restart the dev server
- Verify Better Auth configuration in
lib/auth/auth.ts
- Verify all required API keys are in
.env.local - Check for API rate limits on external services
- Review browser console for error messages
- Ensure tokens haven't expired (especially Spotify refresh token)
- Run
npm installagain to ensure all dependencies are installed - Clear Next.js cache:
rm -rf .next - Verify Node.js version:
node --version(requires 18+) - Check for TypeScript errors:
npm run typecheck
# Test connection string is valid
mongosh "your-connection-string"
# Ensure network access is allowed in MongoDB Atlas
# (IP Whitelist includes your machine's IP)# Use a different port
npm run dev -- -p 3001| Task | Command |
|---|---|
| Start development server | npm run dev |
| Type checking | npm run typecheck |
| Format code | npm run format |
| Lint code | npm run lint |
| Build for production | npm run build |
| Run production server | npm start |
| File | Purpose |
|---|---|
app/page.tsx |
Home page layout |
lib/constants/projects-config.ts |
Featured projects |
models/Profile.ts |
User profile schema |
lib/services/gemini.ts |
AI chat configuration |
tailwind.config.ts |
Theme customization |
- Copy
.env.exampleto.env.local(if example exists) - Add
MONGODB_URI(required) - Add optional integration keys (GitHub, Spotify, etc.)
- Restart dev server:
npm run dev
We welcome contributions! Whether it's bug fixes, feature additions, or documentation improvements, your help makes this portfolio better for everyone.
- Fork the repository
- Create a feature branch
git checkout -b feature/your-feature-name
- Make your changes and ensure code quality
npm run format npm run lint npm run typecheck
- Commit with a clear message
git commit -m "feat: add new integration card" - Push to your fork
git push origin feature/your-feature-name
- Open a Pull Request with a description of your changes
- Use TypeScript for all new code
- Follow the existing code style — run
npm run formatbefore committing - Keep components small and reusable
- Add proper type annotations (no
anytypes) - Test responsive design on mobile and desktop
- UI/UX improvements and design enhancements
- New integrations (Twitch, YouTube, BookStack, etc.)
- Better documentation and guides
- Bug fixes and performance optimizations
- Accessibility improvements
This project is licensed under the MIT License — see LICENSE for details.
You're free to use this portfolio as a template for your own projects!
Questions or Found an Issue?
- Report a Bug
- Request a Feature
- Start a Discussion
- Contact via the portfolio's contact form