A stunning, high-performance developer portfolio website built with cutting-edge technologies
Features โข Tech Stack โข Installation โข Customization โข Deployment โข License
| ๐ฏ Feature | ๐ Description |
|---|---|
| โก Lightning Fast | Built on Next.js 15 with Turbopack for blazing fast development |
| ๐จ Beautiful UI | Polished interface using shadcn/ui, Radix UI, and Tailwind CSS v4 |
| ๐ GitHub Integration | Dynamic widget that auto-fetches your GitHub profile data |
| ๐ง Contact Form | Working email API powered by Nodemailer (Gmail ready) |
| ๐ Theme Support | Seamless dark/light mode toggle with next-themes |
| ๐ผ๏ธ Export Ready | PDF export & screenshot capabilities built-in |
| ๐ Smooth Animations | Fluid animations using Framer Motion |
| ๐งฉ State Management | Efficient state handling with Zustand |
| ๐ Type-Safe | Full TypeScript support for reliability |
| โฟ Accessible | WCAG compliant with Radix UI primitives |
|
Next.js 15 |
React 19 |
TypeScript |
Tailwind v4 |
|
shadcn/ui |
Radix UI |
Framer Motion |
Lucide Icons |
| Category | Technology |
|---|---|
| State Management | Zustand |
| Email Service | Nodemailer |
| PDF Generation | jsPDF |
| Screenshots | html2canvas |
| Audio | Howler.js |
| Animations | tailwindcss-animate |
os-portfolio/
โโโ ๐ src/
โ โโโ ๐ app/
โ โ โโโ ๐ api/
โ โ โ โโโ ๐ send-email/
โ โ โ โโโ ๐ route.ts # Contact form email handler
โ โ โโโ ๐ layout.tsx
โ โ โโโ ๐ page.tsx # Homepage
โ โโโ ๐ components/
โ โ โโโ ๐ os/
โ โ โ โโโ ๐ widgets/
โ โ โ โโโ ๐ github-app.tsx # GitHub Profile Widget
โ โ โโโ ๐ ui/ # shadcn/ui components
โ โโโ ๐ lib/
โ โ โโโ ๐ utils.ts
โ โโโ ๐ styles/
โ โโโ ๐ globals.css
โโโ ๐ public/
โ โโโ ๐ assets/
โโโ ๐ components.json # shadcn/ui config
โโโ ๐ next.config.ts
โโโ ๐ tailwind.config.js
โโโ ๐ tsconfig.json
โโโ ๐ package.json
โโโ ๐ .env.local.example
โโโ ๐ README.md
๐ฆ Prerequisites
- Node.js 18.17 or later
- npm, yarn, or pnpm
- Git
- Gmail account (for contact form)
# 1๏ธโฃ Clone the repository
git clone https://github.com/nerkoux/os-portfolio.git
cd os-portfolio
# 2๏ธโฃ Install dependencies
npm install
# or
yarn install
# or
pnpm install
# 3๏ธโฃ Create environment file
cp .env.local.example .env.local
# 4๏ธโฃ Configure your environment variables
# Edit .env.local and add:
# [email protected]
# SMTP_PASSWORD=your_app_password
# 5๏ธโฃ Run the development server
npm run dev๐ Open http://localhost:3000 in your browser!
Click to expand Gmail configuration steps
- Go to your Google Account
- Navigate to Security โ 2-Step Verification (enable if not already)
- Scroll to App passwords
- Generate a new app password for "Mail"
- Copy the 16-character password
- Add it to your
.env.localfile asSMTP_PASSWORD
๐ก Note: Never use your actual Gmail password. Always use App Passwords for security.
File: src/components/os/widgets/github-app.tsx
// Replace with your GitHub username
const username = 'your-github-username' // ๐ Change this
useEffect(() => {
fetchGitHubData()
}, [])
const fetchGitHubData = async () => {
setLoading(true)
setError(null)
try {
// Add delay to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 100))
// Fetch profile data with proper headers
const profileResponse = await fetch(
`https://api.github.com/users/${username}`,
{
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'Portfolio-App'
}
}
)
if (!profileResponse.ok) throw new Error('Failed to fetch profile')
const profileData = await profileResponse.json()
setProfile(profileData)
// Fetch repositories...
} catch (err) {
setError('Failed to load GitHub data.')
} finally {
setLoading(false)
}
}๐ก Pro Tip: Using GitHub Personal Access Token
For higher API rate limits, add a GitHub token:
// In .env.local
GITHUB_TOKEN=ghp_your_token_here
// In github-app.tsx
const token = process.env.NEXT_PUBLIC_GITHUB_TOKEN
const profileResponse = await fetch(
`https://api.github.com/users/${username}`,
{
headers: {
'Authorization': token ? `Bearer ${token}` : '',
'Accept': 'application/vnd.github.v3+json',
}
}
)File: src/app/api/send-email/route.ts
import { NextResponse } from 'next/server'
import nodemailer from 'nodemailer'
export async function POST(request: Request) {
try {
const { name, email, message } = await request.json()
// Validation
if (!name || !email || !message) {
return NextResponse.json(
{ error: 'Missing required fields' },
{ status: 400 }
)
}
// Gmail SMTP Setup
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.SMTP_EMAIL,
pass: process.env.SMTP_PASSWORD,
},
})
// Send email
await transporter.sendMail({
from: process.env.SMTP_EMAIL,
to: process.env.SMTP_EMAIL, // Your email
subject: `Portfolio Contact: ${name}`,
text: message,
html: `
<h2>New Contact Form Submission</h2>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Message:</strong></p>
<p>${message}</p>
`,
})
return NextResponse.json({ success: true })
} catch (error) {
console.error('Email error:', error)
return NextResponse.json(
{ error: 'Failed to send email' },
{ status: 500 }
)
}
}๐ Alternative Email Providers
Outlook/Hotmail:
service: 'hotmail'Yahoo:
service: 'yahoo'Custom SMTP:
const transporter = nodemailer.createTransport({
host: 'smtp.example.com',
port: 587,
secure: false,
auth: {
user: process.env.SMTP_EMAIL,
pass: process.env.SMTP_PASSWORD,
},
})File: tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
// Customize your color palette
primary: {
50: '#eff6ff',
// ... add your colors
900: '#1e3a8a',
},
},
animation: {
// Add custom animations
'fade-in': 'fadeIn 0.5s ease-in-out',
},
},
},
}# Add individual components
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add input
npx shadcn-ui@latest add dialog
# View all available components
npx shadcn-ui@latest add| Command | Description |
|---|---|
npm run dev |
๐ Start development server with Turbopack |
npm run build |
๐ฆ Build for production |
npm run start |
|
npm run lint |
๐ Run ESLint checks |
npm run type-check |
โ Run TypeScript type checking |
Steps:
- Push your code to GitHub
- Import your repository on Vercel
- Add environment variables:
SMTP_EMAILSMTP_PASSWORD
- Click Deploy ๐
# Build the application
npm run build
# Start production server
npm run startNetlify
# Install Netlify CLI
npm install -g netlify-cli
# Deploy
netlify deploy --prodDocker
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]docker build -t os-portfolio .
docker run -p 3000:3000 os-portfolioAWS (S3 + CloudFront)
# Build static export
npm run build
# Deploy to S3
aws s3 sync out/ s3://your-bucket-name --delete- ๐ Blog Section with MDX support
- ๐ reCAPTCHA Integration for spam protection
- ๐ Analytics Dashboard (Google Analytics / Plausible)
- ๐ i18n Support for multiple languages
- ๐จ Theme Customizer with live preview
- ๐ฑ PWA Support for offline functionality
- ๐ Web Push Notifications
- ๐งช Unit & E2E Tests with Jest and Playwright
- ๐ Admin Panel for content management
- ๐ Performance Monitoring with Sentry
Contributions are always welcome! Here's how you can help:
- ๐ด Fork the repository
- ๐ฟ Create a feature branch (
git checkout -b feature/AmazingFeature) - ๐พ Commit your changes (
git commit -m 'Add some AmazingFeature') - ๐ค Push to the branch (
git push origin feature/AmazingFeature) - ๐ Open a Pull Request
๐ Contribution Guidelines
- Follow the existing code style
- Write meaningful commit messages
- Update documentation as needed
- Add tests for new features
- Ensure all tests pass before submitting PR
Found a bug? Have a feature suggestion? Please open an issue with:
- ๐ Clear description of the bug/feature
- ๐ธ Screenshots (if applicable)
- ๐ Steps to reproduce (for bugs)
- ๐ก Expected behavior
- ๐ฅ๏ธ Environment details
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2025 Akshat Mehta
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction...
If you found this project helpful, please consider:





