blocks for different files, but since this is a Next.js project with many files, I'll organize it as a multi-file project. Actually, looking at the instructions, for multi-file websites I should use MULTIPLE [WEBSITE_PREVIEW] blocks, one per file, with a filename line. Let me create the complete project structure. This will be many files, so I'll need to be comprehensive but organized. Let me start with the essential files: 1. package.json 2. tsconfig.json 3. tailwind.config.ts 4. next.config.js 5. .env.example 6. Directory structure files 7. Components 8. Pages/App Router routes 9. API routes 10. Admin panel 11. Database models 12. Utilities This is going to be a very long response with many [WEBSITE_PREVIEW] blocks. Let me start.[WEBSITE_PREVIEW] { "name": "mubarak-portfolio", "version": "1.0.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "db:seed": "tsx scripts/seed.ts", "postinstall": "prisma generate" }, "dependencies": { "next": "14.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", "framer-motion": "^11.0.0", "lucide-react": "^0.344.0", "mongoose": "^8.2.0", "jsonwebtoken": "^9.0.2", "bcryptjs": "^2.4.3", "zod": "^3.22.4", "react-hook-form": "^7.51.0", "@hookform/resolvers": "^3.3.4", "nodemailer": "^6.9.10", "next-cloudinary": "^6.0.0", "next-pwa": "^5.6.0", "sharp": "^0.33.2", "react-hot-toast": "^2.4.1", "react-intersection-observer": "^9.8.0", "clsx": "^2.1.0", "tailwind-merge": "^2.2.1", "date-fns": "^3.3.1", "canvas-confetti": "^1.9.2" }, "devDependencies": { "@types/node": "^20.11.0", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", "@types/jsonwebtoken": "^9.0.5", "@types/bcryptjs": "^2.4.6", "@types/nodemailer": "^6.4.14", "@types/canvas-confetti": "^1.6.4", "typescript": "^5.3.0", "tailwindcss": "^3.4.0", "postcss": "^8.4.35", "autoprefixer": "^10.4.17", "eslint": "^8.56.0", "eslint-config-next": "14.2.0", "prettier": "^3.2.5", "prettier-plugin-tailwindcss": "^0.5.11", "tsx": "^4.7.0", "prisma": "^5.10.0", "@prisma/client": "^5.10.0" } } { "compilerOptions": { "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./src/*"] }, "baseUrl": "." }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] } import type { Config } from 'tailwindcss' const config: Config = { content: [ './src/pages/**/*.{js,ts,jsx,tsx,mdx}', './src/components/**/*.{js,ts,jsx,tsx,mdx}', './src/app/**/*.{js,ts,jsx,tsx,mdx}', ], darkMode: 'class', theme: { extend: { colors: { primary: { 50: '#f0f4ff', 100: '#e0e9ff', 200: '#c7d7ff', 300: '#a3bbff', 400: '#7a94ff', 500: '#5a6fff', 600: '#4353eb', 700: '#3740c4', 800: '#31379e', 900: '#2d3080', 950: '#1e1b52', }, neon: { blue: '#00d4ff', purple: '#a855f7', pink: '#ec4899', green: '#22c55e', }, dark: { 50: '#f8fafc', 100: '#f1f5f9', 200: '#e2e8f0', 300: '#cbd5e1', 400: '#94a3b8', 500: '#64748b', 600: '#475569', 700: '#334155', 800: '#1e293b', 900: '#0f172a', 950: '#020617', }, glass: { light: 'rgba(255, 255, 255, 0.05)', medium: 'rgba(255, 255, 255, 0.1)', heavy: 'rgba(255, 255, 255, 0.15)', } }, fontFamily: { sans: ['var(--font-poppins)', 'system-ui', 'sans-serif'], display: ['var(--font-space-grotesk)', 'system-ui', 'sans-serif'], mono: ['var(--font-geist-mono)', 'monospace'], }, fontSize: { 'fluid-xs': 'clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem)', 'fluid-sm': 'clamp(0.875rem, 0.8rem + 0.375vw, 1rem)', 'fluid-base': 'clamp(1rem, 0.9rem + 0.5vw, 1.125rem)', 'fluid-lg': 'clamp(1.125rem, 1rem + 0.625vw, 1.25rem)', 'fluid-xl': 'clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem)', 'fluid-2xl': 'clamp(1.5rem, 1.25rem + 1.25vw, 2rem)', 'fluid-3xl': 'clamp(1.875rem, 1.5rem + 1.875vw, 3rem)', 'fluid-4xl': 'clamp(2.25rem, 1.75rem + 2.5vw, 4rem)', 'fluid-5xl': 'clamp(3rem, 2rem + 5vw, 6rem)', }, spacing: { '18': '4.5rem', '88': '22rem', '128': '32rem', }, animation: { 'aurora': 'aurora 20s ease-in-out infinite', 'float': 'float 6s ease-in-out infinite', 'pulse-glow': 'pulse-glow 3s ease-in-out infinite', 'slide-up': 'slide-up 0.8s ease-out forwards', 'slide-down': 'slide-down 0.5s ease-out forwards', 'fade-in': 'fade-in 0.6s ease-out forwards', 'scale-in': 'scale-in 0.4s ease-out forwards', 'rotate-slow': 'rotate-slow 20s linear infinite', 'shimmer': 'shimmer 2s ease-in-out infinite', 'ripple': 'ripple 0.6s ease-out', 'spin-slow': 'spin 8s linear infinite', 'bounce-slow': 'bounce 3s ease-in-out infinite', }, keyframes: { aurora: { '0%, 100%': { backgroundPosition: '0% 50%' }, '50%': { backgroundPosition: '100% 50%' }, }, float: { '0%, 100%': { transform: 'translateY(0px) rotate(0deg)' }, '50%': { transform: 'translateY(-20px) rotate(5deg)' }, }, 'pulse-glow': { '0%, 100%': { boxShadow: '0 0 20px rgba(0, 212, 255, 0.3), 0 0 40px rgba(168, 85, 247, 0.2)' }, '50%': { boxShadow: '0 0 40px rgba(0, 212, 255, 0.5), 0 0 80px rgba(168, 85, 247, 0.4)' }, }, 'slide-up': { 'from': { opacity: '0', transform: 'translateY(40px)' }, 'to': { opacity: '1', transform: 'translateY(0)' }, }, 'slide-down': { 'from': { opacity: '0', transform: 'translateY(-20px)' }, 'to': { opacity: '1', transform: 'translateY(0)' }, }, 'fade-in': { 'from': { opacity: '0' }, 'to': { opacity: '1' }, }, 'scale-in': { 'from': { opacity: '0', transform: 'scale(0.9)' }, 'to': { opacity: '1', transform: 'scale(1)' }, }, 'rotate-slow': { 'from': { transform: 'rotate(0deg)' }, 'to': { transform: 'rotate(360deg)' }, }, shimmer: { '0%': { backgroundPosition: '-200% 0' }, '100%': { backgroundPosition: '200% 0' }, }, ripple: { '0%': { transform: 'scale(0)', opacity: '0.5' }, '100%': { transform: 'scale(4)', opacity: '0' }, }, }, backgroundImage: { 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 'mesh-gradient': 'linear-gradient(135deg, #0f172a 0%, #1e1b4b 50%, #0f172a 100%)', 'aurora-gradient': 'linear-gradient(45deg, #00d4ff, #a855f7, #ec4899, #00d4ff)', 'noise': "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E\")", }, backdropBlur: { xs: '2px', '4xl': '72px', }, boxShadow: { 'neon-blue': '0 0 20px rgba(0, 212, 255, 0.5), 0 0 40px rgba(0, 212, 255, 0.3), 0 0 60px rgba(0, 212, 255, 0.1)', 'neon-purple': '0 0 20px rgba(168, 85, 247, 0.5), 0 0 40px rgba(168, 85, 247, 0.3), 0 0 60px rgba(168, 85, 247, 0.1)', 'neon-pink': '0 0 20px rgba(236, 72, 153, 0.5), 0 0 40px rgba(236, 72, 153, 0.3), 0 0 60px rgba(236, 72, 153, 0.1)', 'glass': '0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)', 'glass-hover': '0 12px 40px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.15)', 'inner-glow': 'inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.1)', }, borderRadius: { '4xl': '2rem', '5xl': '2.5rem', }, transitionDuration: { '400': '400ms', '600': '600ms', }, transitionTimingFunction: { 'spring': 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 'bounce': 'cubic-bezier(0.68, -0.55, 0.265, 1.55)', }, }, }, plugins: [], } export default config /** @type {import('next').NextConfig} */ const withPWA = require('next-pwa')({ dest: 'public', register: true, skipWaiting: true, disable: process.env.NODE_ENV === 'development', }) const nextConfig = { reactStrictMode: true, images: { remotePatterns: [ { protocol: 'https', hostname: '**', }, ], formats: ['image/avif', 'image/webp'], }, experimental: { optimizePackageImports: ['lucide-react', 'framer-motion'], }, headers: async () => [ { source: '/:path*', headers: [ { key: 'X-DNS-Prefetch-Control', value: 'on', }, { key: 'X-Content-Type-Options', value: 'nosniff', }, { key: 'Referrer-Policy', value: 'origin-when-cross-origin', }, ], }, ], } module.exports = withPWA(nextConfig) # Database DATABASE_URL="mongodb://localhost:27017/portfolio?retryWrites=true&w=majority" # Auth JWT_SECRET="your-super-secret-jwt-key-min-32-chars" JWT_EXPIRES_IN="7d" ADMIN_USERNAME="admin" ADMIN_PASSWORD="your-secure-password" # Email (Nodemailer) SMTP_HOST="smtp.gmail.com" SMTP_PORT="587" SMTP_USER="your-email@gmail.com" SMTP_PASS="your-app-password" EMAIL_FROM="Portfolio " # Cloudinary (Image Upload) NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="your-cloud-name" CLOUDINARY_API_KEY="your-api-key" CLOUDINARY_API_SECRET="your-api-secret" # Analytics NEXT_PUBLIC_GA_ID="G-XXXXXXXXXX" # Site NEXT_PUBLIC_SITE_URL="https://yourdomain.com" NEXT_PUBLIC_SITE_NAME="Mubarak Portfolio" import { clsx, type ClassValue } from 'clsx' import { twMerge } from 'tailwind-merge' export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } export function formatNumber(num: number): string { if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M' if (num >= 1000) return (num / 1000).toFixed(1) + 'K' return num.toString() } export function generateId(): string { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) } export function debounce unknown>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout | null = null return (...args: Parameters) => { if (timeout) clearTimeout(timeout) timeout = setTimeout(() => func(...args), wait) } } export function throttle unknown>( func: T, limit: number ): (...args: Parameters) => void { let inThrottle = false return (...args: Parameters) => { if (!inThrottle) { func(...args) inThrottle = true setTimeout(() => (inThrottle = false), limit) } } } import mongoose from 'mongoose' const MONGODB_URI = process.env.DATABASE_URL! if (!MONGODB_URI) { throw new Error('Please define the DATABASE_URL environment variable inside .env') } interface GlobalMongoose { conn: typeof mongoose | null promise: Promise | null } declare global { var mongoose: GlobalMongoose | undefined } let cached = global.mongoose if (!cached) { cached = global.mongoose = { conn: null, promise: null } } async function connectDB(): Promise { if (cached!.conn) { return cached!.conn } if (!cached!.promise) { const opts = { bufferCommands: false, maxPoolSize: 10, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 45000, } cached!.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => { return mongoose }) } try { cached!.conn = await cached!.promise } catch (e) { cached!.promise = null throw e } return cached!.conn } export default connectDB import mongoose, { Document, Schema } from 'mongoose' export interface ISettings extends Document { // General siteName: string siteDescription: string siteUrl: string authorName: string authorTitle: string authorBio: string profileImage: string resumeUrl: string favicon: string logo: string // Hero Section hero: { enabled: boolean greeting: string name: string titles: string[] description: string primaryButton: { text: string; url: string; icon: string } secondaryButton: { text: string; url: string; icon: string } } // About Section about: { enabled: boolean title: string subtitle: string description: string image: string stats: Array<{ label: string; value: string; icon: string }> skills: string[] } // Skills Section skills: { enabled: boolean title: string subtitle: string categories: Array<{ name: string skills: Array<{ name: string; level: number; icon: string; color: string }> }> } // Projects Section projects: { enabled: boolean title: string subtitle: string items: Array<{ id: string title: string description: string shortDescription: string image: string category: string technologies: string[] liveUrl: string githubUrl: string featured: boolean order: number }> } // Social Links social: { enabled: boolean links: Array<{ id: string platform: string username: string url: string icon: string color: string enabled: boolean }> } // Services Section services: { enabled: boolean title: string subtitle: string items: Array<{ id: string title: string description: string icon: string features: string[] price: string order: number }> } // Contact Section contact: { enabled: boolean title: string subtitle: string email: string discord: string phone: string address: string formEnabled: boolean } // Footer footer: { enabled: boolean copyright: string links: Array<{ label: string; url: string }> socialLinks: Array<{ platform: string; url: string }> } // Theme theme: { primaryColor: string secondaryColor: string accentColor: string fontPrimary: string fontSecondary: string darkMode: boolean animationsEnabled: boolean } // SEO seo: { title: string description: string keywords: string[] ogImage: string twitterHandle: string googleAnalytics: string googleSiteVerification: string } // Features features: { visitorCounter: boolean newsletterEnabled: boolean contactFormEnabled: boolean blogEnabled: boolean adminPanelEnabled: boolean } // Meta createdAt: Date updatedAt: Date } const SettingsSchema = new Schema({ siteName: { type: String, default: 'Mubarak Portfolio' }, siteDescription: { type: String, default: 'Full Stack Developer Portfolio' }, siteUrl: { type: String, default: 'https://mubarak.dev' }, authorName: { type: String, default: 'Mubarak' }, authorTitle: { type: String, default: 'Full Stack Developer' }, authorBio: { type: String, default: 'I build premium Discord Bots, Telegram Bots, Minecraft Systems, Automation Tools and Modern Websites.' }, profileImage: { type: String, default: '' }, resumeUrl: { type: String, default: '' }, favicon: { type: String, default: '' }, logo: { type: String, default: '' }, hero: { enabled: { type: Boolean, default: true }, greeting: { type: String, default: '👋 Hi, I\'m Mubarak' }, name: { type: String, default: 'Mubarak' }, titles: { type: [String], default: ['Full Stack Developer', 'Discord Bot Developer', 'Telegram Bot Developer', 'Minecraft Developer'] }, description: { type: String, default: 'I build premium Discord Bots, Telegram Bots, Minecraft Systems, Automation Tools and Modern Websites.' }, primaryButton: { text: { type: String, default: 'Hire Me' }, url: { type: String, default: '#contact' }, icon: { type: String, default: 'rocket' } }, secondaryButton: { text: { type: String, default: 'My Projects' }, url: { type: String, default: '#projects' }, icon: { type: String, default: 'briefcase' } }, }, about: { enabled: { type: Boolean, default: true }, title: { type: String, default: 'About Me' }, subtitle: { type: String, default: 'Get to know me better' }, description: { type: String, default: 'I\'m a passionate Full Stack Developer with expertise in building scalable web applications, Discord/Telegram bots, and Minecraft systems. With years of experience in modern technologies, I love creating innovative solutions that solve real-world problems.' }, image: { type: String, default: '' }, stats: { type: [{ label: String, value: String, icon: String, }], default: [ { label: 'Projects Completed', value: '50+', icon: 'folder-open' }, { label: 'Happy Clients', value: '30+', icon: 'users' }, { label: 'Years Experience', value: '5+', icon: 'calendar' }, { label: 'Lines of Code', value: '100K+', icon: 'code' }, ], }, skills: { type: [String], default: ['React', 'Next.js', 'TypeScript', 'Node.js', 'MongoDB', 'Discord.js', 'Python'] }, }, skills: { enabled: { type: Boolean, default: true }, title: { type: String, default: 'Skills & Technologies' }, subtitle: { type: String, default: 'Technologies I work with' }, categories: { type: [{ name: String, skills: [{ name: String, level: Number, icon: String, color: String, }], }], default: [ { name: 'Frontend', skills: [ { name: 'React', level: 95, icon: 'code', color: '#61dafb' }, { name: 'Next.js', level: 90, icon: 'zap', color: '#000000' }, { name: 'TypeScript', level: 88, icon: 'file-code', color: '#3178c6' }, { name: 'Tailwind CSS', level: 92, icon: 'palette', color: '#06b6d4' }, ], }, { name: 'Backend', skills: [ { name: 'Node.js', level: 90, icon: 'server', color: '#339933' }, { name: 'MongoDB', level: 85, icon: 'database', color: '#47a248' }, { name: 'MySQL', level: 80, icon: 'cylinder', color: '#4479a1' }, { name: 'Firebase', level: 82, icon: 'cloud', color: '#ffca28' }, ], }, { name: 'Bot Development', skills: [ { name: 'Discord.js', level: 95, icon: 'bot', color: '#5865f2' }, { name: 'Telegram Bot API', level: 88, icon: 'send', color: '#0088cc' }, { name: 'Minecraft Plugins', level: 85, icon: 'cube', color: '#62b47b' }, ], }, ], }, }, projects: { enabled: { type: Boolean, default: true }, title: { type: String, default: 'Featured Projects' }, subtitle: { type: String, default: 'Some of my recent work' }, items: { type: [Schema.Types.Mixed], default: [] }, }, social: { enabled: { type: Boolean, default: true }, links: { type: [{ id: String, platform: String, username: String, url: String, icon: String, color: String, enabled: Boolean, }], default: [ { id: '1', platform: 'TikTok', username: '@mubarak.694', url: 'https://www.tiktok.com/@mubarak.694?_r=1&_t=ZS-98EZdiZE6tc', icon: 'music', color: '#000000', enabled: true }, { id: '2', platform: 'YouTube', username: '@epicxp73', url: 'https://youtube.com/@epicxp73?si=DL4EPKqr0AohaEkp', icon: 'youtube', color: '#ff0000', enabled: true }, { id: '3', platform: 'Facebook', username: 'Mubarak', url: 'https://www.facebook.com/share/1CSUf3s5Lb/', icon: 'facebook', color: '#1877f2', enabled: true }, { id: '4', platform: 'Discord', username: 'mubarak_44', url: 'https://discord.com/users/mubarak_44', icon: 'message-circle', color: '#5865f2', enabled: true }, ], }, }, services: { enabled: { type: Boolean, default: true }, title: { type: String, default: 'Services' }, subtitle: { type: String, default: 'What I can do for you' }, items: { type: [{ id: String, title: String, description: String, icon: String, features: [String], price: String, order: Number, }], default: [ { id: '1', title: 'Discord Bot Development', description: 'Custom Discord bots with advanced features, dashboard, and database integration.', icon: 'bot', features: ['Slash Commands', 'Dashboard', 'Database', 'Music', 'Moderation', 'Economy'], price: 'Starting at $100', order: 1 }, { id: '2', title: 'Telegram Bot Development', description: 'Powerful Telegram bots with inline queries, payments, and custom keyboards.', icon: 'send', features: ['Inline Mode', 'Payments', 'Web Apps', 'Groups/Channels', 'Auto-posting'], price: 'Starting at $80', order: 2 }, { id: '3', title: 'Website Development', description: 'Modern, responsive websites built with Next.js, React, and Tailwind CSS.', icon: 'globe', features: ['Next.js 14', 'TypeScript', 'Tailwind CSS', 'SEO Optimized', 'PWA Ready', 'CMS Integration'], price: 'Starting at $500', order: 3 }, { id: '4', title: 'Minecraft Development', description: 'Custom Spigot/Paper plugins, mods, and server systems.', icon: 'cube', features: ['Spigot/Paper', 'BungeeCord', 'Database', 'GUI Menus', 'Economy', 'Custom Items'], price: 'Starting at $150', order: 4 }, { id: '5', title: 'API Development', description: 'RESTful and GraphQL APIs with authentication, rate limiting, and documentation.', icon: 'code', features: ['REST/GraphQL', 'JWT Auth', 'Rate Limiting', 'Swagger Docs', 'Testing', 'Deployment'], price: 'Starting at $200', order: 5 }, { id: '6', title: 'Automation Tools', description: 'Custom automation scripts and tools for workflow optimization.', icon: 'zap', features: ['Web Scraping', 'API Integration', 'Scheduled Tasks', 'Data Processing', 'Notifications', 'Cloud Deployment'], price: 'Starting at $100', order: 6 }, ], }, }, contact: { enabled: { type: Boolean, default: true }, title: { type: String, default: 'Get In Touch' }, subtitle: { type: String, default: 'Have a project in mind? Let\'s talk!' }, email: { type: String, default: 'hello@mubarak.dev' }, discord: { type: String, default: 'mubarak_44' }, phone: { type: String, default: '' }, address: { type: String, default: '' }, formEnabled: { type: Boolean, default: true }, }, footer: { enabled: { type: Boolean, default: true }, copyright: { type: String, default: '© 2024 Mubarak. All rights reserved.' }, links: { type: [{ label: String, url: String }], default: [ { label: 'Privacy Policy', url: '/privacy' }, { label: 'Terms of Service', url: '/terms' }, { label: 'Sitemap', url: '/sitemap.xml' }, ], }, socialLinks: { type: [{ platform: String, url: String }], default: [], }, }, theme: { primaryColor: { type: String, default: '#00d4ff' }, secondaryColor: { type: String, default: '#a855f7' }, accentColor: { type: String, default: '#ec4899' }, fontPrimary: { type: String, default: 'Poppins' }, fontSecondary: { type: String, default: 'Space Grotesk' }, darkMode: { type: Boolean, default: true }, animationsEnabled: { type: Boolean, default: true }, }, seo: { title: { type: String, default: 'Mubarak | Full Stack Developer' }, description: { type: String, default: 'Full Stack Developer specializing in Discord Bots, Telegram Bots, Minecraft Systems, and Modern Web Applications.' }, keywords: { type: [String], default: ['Full Stack Developer', 'Discord Bot', 'Telegram Bot', 'Minecraft', 'Next.js', 'React', 'TypeScript'] }, ogImage: { type: String, default: '' }, twitterHandle: { type: String, default: '@mubarak_dev' }, googleAnalytics: { type: String, default: '' }, googleSiteVerification: { type: String, default: '' }, }, features: { visitorCounter: { type: Boolean, default: true }, newsletterEnabled: { type: Boolean, default: false }, contactFormEnabled: { type: Boolean, default: true }, blogEnabled: { type: Boolean, default: false }, adminPanelEnabled: { type: Boolean, default: true }, }, }, { timestamps: true }) export default mongoose.models.Settings || mongoose.model('Settings', SettingsSchema) import mongoose, { Document, Schema } from 'mongoose' export interface IContactMessage extends Document { name: string email: string subject: string message: string status: 'unread' | 'read' | 'replied' | 'archived' ip: string userAgent: string repliedAt?: Date repliedBy?: string createdAt: Date updatedAt: Date } const ContactMessageSchema = new Schema({ name: { type: String, required: true, trim: true, maxlength: 100 }, email: { type: String, required: true, trim: true, lowercase: true, maxlength: 255 }, subject: { type: String, required: true, trim: true, maxlength: 200 }, message: { type: String, required: true, trim: true, maxlength: 5000 }, status: { type: String, enum: ['unread', 'read', 'replied', 'archived'], default: 'unread' }, ip: { type: String, required: true }, userAgent: { type: String, required: true }, repliedAt: { type: Date }, repliedBy: { type: String }, }, { timestamps: true }) ContactMessageSchema.index({ createdAt: -1 }) ContactMessageSchema.index({ status: 1 }) ContactMessageSchema.index({ email: 1 }) export default mongoose.models.ContactMessage || mongoose.model('ContactMessage', ContactMessageSchema) import mongoose, { Document, Schema } from 'mongoose' export interface IVisitor extends Document { count: number uniqueVisitors: number lastReset: Date dailyStats: Array<{ date: string count: number unique: number }> createdAt: Date updatedAt: Date } const VisitorSchema = new Schema({ count: { type: Number, default: 0 }, uniqueVisitors: { type: Number, default: 0 }, lastReset: { type: Date, default: Date.now }, dailyStats: { type: [{ date: { type: String, required: true }, count: { type: Number, default: 0 }, unique: { type: Number, default: 0 }, }], default: [], }, }, { timestamps: true }) export default mongoose.models.Visitor || mongoose.model('Visitor', VisitorSchema) import jwt from 'jsonwebtoken' import bcrypt from 'bcryptjs' import { cookies } from 'next/headers' const JWT_SECRET = process.env.JWT_SECRET! const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d' export interface TokenPayload { userId: string username: string role: string iat?: number exp?: number } export async function hashPassword(password: string): Promise { return bcrypt.hash(password, 12) } export async function verifyPassword(password: string, hashedPassword: string): Promise { return bcrypt.compare(password, hashedPassword) } export function generateToken(payload: Omit): string { return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN }) } export function verifyToken(token: string): TokenPayload | null { try { return jwt.verify(token, JWT_SECRET) as TokenPayload } catch { return null } } export async function getSession(): Promise { const cookieStore = await cookies() const token = cookieStore.get('admin_token')?.value if (!token) return null return verifyToken(token) } export async function setAuthCookie(token: string) { const cookieStore = await cookies() cookieStore.set('admin_token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', maxAge: 60 * 60 * 24 * 7, // 7 days path: '/', }) } export async function removeAuthCookie() { const cookieStore = await cookies() cookieStore.delete('admin_token') } import nodemailer from 'nodemailer' const transporter = nodemailer.createTransport({ host: process.env.SMTP_HOST, port: parseInt(process.env.SMTP_PORT || '587'), secure: false, auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS, }, }) export async function sendContactEmail(data: { name: string email: string subject: string message: string }) { const { name, email, subject, message } = data await transporter.sendMail({ from: process.env.EMAIL_FROM, to: process.env.SMTP_USER, subject: `New Contact: ${subject}`, html: `

New Contact Form Submission

Name: ${name}

Email: ${email}

Subject: ${subject}

Message:

${message}


Sent from portfolio contact form

`, }) // Send auto-reply to user await transporter.sendMail({ from: process.env.EMAIL_FROM, to: email, subject: `Thanks for reaching out, ${name}!`, html: `

Thanks for contacting me!

Hi ${name},

I've received your message and will get back to you as soon as possible. Usually within 24-48 hours.

Your message:

${message}

Best regards,
Mubarak


This is an automated response. Please do not reply to this email.

`, }) } export async function sendReplyEmail(data: { to: string name: string originalSubject: string originalMessage: string reply: string }) { const { to, name, originalSubject, originalMessage, reply } = data await transporter.sendMail({ from: process.env.EMAIL_FROM, to, subject: `Re: ${originalSubject}`, html: `

Reply from Mubarak

Hi ${name},

${reply.replace(/\n/g, '
')}

Original Message

Subject: ${originalSubject}

${originalMessage}

This is a reply to your contact form submission.

`, }) } 'use client' import { forwardRef, type HTMLAttributes } from 'react' import { cn } from '@/lib/utils' interface GlassCardProps extends HTMLAttributes { variant?: 'light' | 'medium' | 'heavy' | 'neon-blue' | 'neon-purple' | 'neon-pink' hover?: boolean glow?: boolean } export const GlassCard = forwardRef( ({ className, variant = 'medium', hover = true, glow = false, children, ...props }, ref) => { const baseStyles = ` backdrop-blur-xl border rounded-2xl transition-all duration-500 ease-spring ` const variants = { light: 'bg-glass-light border-white/10', medium: 'bg-glass-medium border-white/20', heavy: 'bg-glass-heavy border-white/30', 'neon-blue': 'bg-glass-medium border-neon-blue/30 shadow-neon-blue', 'neon-purple': 'bg-glass-medium border-neon-purple/30 shadow-neon-purple', 'neon-pink': 'bg-glass-medium border-neon-pink/30 shadow-neon-pink', } const hoverStyles = hover ? 'hover:shadow-glass-hover hover:border-white/30 hover:scale-[1.02]' : '' const glowStyles = glow ? 'animate-pulse-glow' : '' return (
{children}
) } ) GlassCard.displayName = 'GlassCard' 'use client' import { forwardRef, type ButtonHTMLAttributes } from 'react' import { cn } from '@/lib/utils' import { Loader2 } from 'lucide-react' interface ButtonProps extends ButtonHTMLAttributes { variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'neon-blue' | 'neon-purple' | 'neon-pink' size?: 'sm' | 'md' | 'lg' | 'xl' loading?: boolean ripple?: boolean fullWidth?: boolean } export const Button = forwardRef( ({ className, variant = 'primary', size = 'md', loading, ripple = true, fullWidth = false, children, disabled, ...props }, ref) => { const baseStyles = ` inline-flex items-center justify-center gap-2 font-semibold rounded-xl transition-all duration-300 ease-spring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-dark-950 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:transform-none relative overflow-hidden ` const variants = { primary: ` bg-gradient-to-r from-primary-600 to-primary-500 text-white hover:from-primary-500 hover:to-primary-400 hover:shadow-neon-blue focus-visible:ring-primary-500 shadow-lg shadow-primary-500/25 `, secondary: ` bg-gradient-to-r from-dark-800 to-dark-700 text-white border border-white/20 hover:border-white/40 hover:bg-dark-700/50 focus-visible:ring-white/30 `, outline: ` bg-transparent text-white border-2 border-white/30 hover:bg-white/10 hover:border-white/50 focus-visible:ring-white/30 `, ghost: ` bg-transparent text-white hover:bg-white/10 focus-visible:ring-white/20 `, 'neon-blue': ` bg-gradient-to-r from-neon-blue to-blue-500 text-dark-950 font-bold hover:from-blue-400 hover:to-neon-blue hover:shadow-neon-blue hover:scale-105 focus-visible:ring-neon-blue shadow-neon-blue `, 'neon-purple': ` bg-gradient-to-r from-neon-purple to-purple-500 text-white font-bold hover:from-purple-500 hover:to-neon-purple hover:shadow-neon-purple hover:scale-105 focus-visible:ring-neon-purple shadow-neon-purple `, 'neon-pink': ` bg-gradient-to-r from-neon-pink to-pink-500 text-white font-bold hover:from-pink-500 hover:to-neon-pink hover:shadow-neon-pink hover:scale-105 focus-visible:ring-neon-pink shadow-neon-pink `, } const sizes = { sm: 'px-4 py-2 text-sm gap-1.5', md: 'px-6 py-3 text-base gap-2', lg: 'px-8 py-4 text-lg gap-2.5', xl: 'px-10 py-5 text-xl gap-3', } const widthStyle = fullWidth ? 'w-full' : '' return ( ) } ) Button.displayName = 'Button' 'use client' import { forwardRef, type InputHTMLAttributes, type TextareaHTMLAttributes } from 'react' import { cn } from '@/lib/utils' interface InputProps extends InputHTMLAttributes { label?: string error?: string helperText?: string } export const Input = forwardRef( ({ className, label, error, helperText, id, ...props }, ref) => { const inputId = id || label?.toLowerCase().replace(/\s+/g, '-') return (
{label && ( )} {error &&

{error}

} {helperText && !error &&

{helperText}

}
) } ) Input.displayName = 'Input' interface TextareaProps extends TextareaHTMLAttributes { label?: string error?: string helperText?: string } export const Textarea = forwardRef( ({ className, label, error, helperText, id, ...props }, ref) => { const textareaId = id || label?.toLowerCase().replace(/\s+/g, '-') return (
{label && ( )}