A modern, full-stack portfolio and resume website with a secure admin panel for content management. Built with Next.js 15, TypeScript, Prisma, and Tailwind CSS v4.
- Interactive Resume: Expandable timeline with work experience, education, skills, and certifications
- Portfolio/Blog: Rich content management with image uploads and markdown support
- Responsive Design: Mobile-first design that works beautifully on all devices
- Dark Mode: Automatic dark/light theme with system preference detection
- SEO Optimized: Meta tags, Open Graph, structured data (JSON-LD)
- Performance: Server-side rendering, optimized images, and fast page loads
- Secure Authentication: NextAuth.js with email whitelist protection
- Content Management: Easy-to-use interface for updating all resume sections
- Real-time Editing: Edit and preview your content instantly
- Image Uploads: Upload profile photos and article images (base64 storage)
- Drag & Drop: Reorder experiences, skills, and portfolio items
- Data Validation: Zod schemas ensure data integrity
- Framework: Next.js 15 (App Router)
- Language: TypeScript
- Database: PostgreSQL with Prisma ORM
- Styling: Tailwind CSS v4
- Authentication: NextAuth.js
- Animations: Framer Motion
- Validation: Zod
- Icons: Lucide React
- Node.js 18+ and npm/yarn/pnpm
- PostgreSQL database (local or hosted)
- Git for version control
git clone https://github.com/TheExtravagantHobo/ehl-resume-homepage.git
cd ehl-resume-homepage
npm installCopy the example environment file:
cp .env.example .env.localEdit .env.local with your configuration:
# Database - PostgreSQL connection string
DATABASE_URL="postgresql://user:password@localhost:5432/portfolio?sslmode=require"
# NextAuth - Authentication
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="generate-this-with-openssl-rand-base64-32"
# Admin Access - Comma-separated list of authorized emails
ADMIN_EMAILS="your-email@example.com"
# Optional - Custom domain for production
NEXT_PUBLIC_BASE_URL="https://your-domain.com"Generate NEXTAUTH_SECRET:
openssl rand -base64 32# Generate Prisma Client
npx prisma generate
# Push schema to database (creates tables)
npx prisma db push
# Seed with example data
npx prisma db seedThe seed will create:
- Admin user:
admin@example.com/admin123 - Example resume for "Jane Developer"
- Sample experiences, education, skills, etc.
npm run devOpen http://localhost:3000 to see your site!
Admin panel: http://localhost:3000/admin
Edit app/globals.css to customize your brand colors:
@theme {
--color-brand-orange: #3B82F6; /* Primary accent - Change to your color */
--color-brand-orange-light: #60A5FA; /* Hover state - Lighter version */
--color-brand-navy: #1E293B; /* Text and dark elements */
}The template uses semantic naming:
brand-orange= Primary accent color (buttons, links, CTAs)brand-orange-light= Hover statesbrand-navy= Text and dark UI elements
Color Palette Suggestions:
- Blue:
#3B82F6and#60A5FA(default) - Purple:
#8B5CF6and#A78BFA - Green:
#10B981and#34D399 - Orange:
#F59E0Band#FBBF24 - Pink:
#EC4899and#F472B6
The template does not include favicons by default. You'll need to add your own:
- Generate Favicons: Use a tool like favicon.io or realfavicongenerator.net
- Add to
/public:favicon.ico(32x32)favicon-16x16.pngfavicon-32x32.pngapple-touch-icon.png(180x180)
- Optional: Add
og-image.png(1200x630) for social media sharing
Tip: Use your brand colors from globals.css when creating favicons for consistency.
- Login: Visit
/adminwith the seeded credentials - Profile Tab: Update your name, title, bio, and contact info
- Add Content: Use the tabs to add experiences, education, skills, etc.
- Upload Images: Click upload buttons for profile photo and portfolio images
- Save: Click "Save All Changes" to persist your updates
Edit showcase tiles in the Admin Panel under the Showcase tab:
- Create custom tiles linking to internal pages or external URLs
- Add images, descriptions, and link types (internal, external, mailto)
- Reorder tiles by changing the order number
- Toggle active/inactive status
Update app/layout.tsx for global metadata:
export const metadata: Metadata = {
title: 'Your Name - Portfolio',
description: 'Your professional description',
// ... customize other fields
}# Development
npm run dev # Start dev server (http://localhost:3000)
# Production
npm run build # Build for production
npm start # Start production server
# Database
npm run db:push # Push schema changes to database
npm run db:migrate # Create and run migrations
npm run db:seed # Seed database with example data
npx prisma studio # Open Prisma Studio GUI
# Code Quality
npm run type-check # Run TypeScript type checking
npm run lint # Run ESLint
# Utilities
npm run clean # Remove .next build directory
npm run analyze # Analyze bundle sizeThe application uses these main models:
- User: Admin authentication accounts
- Resume: Core profile (name, bio, contact info)
- Experience: Work history with expandable bullet points
- Education: Academic background
- Skill: Technical and soft skills with proficiency levels
- Certification: Professional certifications with icons
- Language: Language proficiencies
- Publication: Academic or professional publications
- Showcase: Landing page tiles/cards
- Article: Portfolio/blog posts
See prisma/schema.prisma for full schema details.
-
Push to GitHub:
git add . git commit -m "Initial commit" git push origin main
-
Import on Vercel: vercel.com/new
- Select your repository
- Vercel auto-detects Next.js
-
Set Environment Variables: Add all variables from
.env.exampleDATABASE_URLNEXTAUTH_URL(use your Vercel URL)NEXTAUTH_SECRETADMIN_EMAILSNEXT_PUBLIC_BASE_URL
-
Deploy: Click "Deploy"
After first deployment:
# Run migrations in Vercel's terminal or locally targeting production DB
npx prisma migrate deploy
npx prisma db seedCompatible with any platform supporting Next.js:
- Netlify: Use Next.js runtime
- Railway: Supports Next.js + PostgreSQL
- Render: Configure build command as
npm run build - Self-hosted: Use
npm run build && npm start
Choose a PostgreSQL provider:
- Vercel Postgres: Integrated with Vercel deployments
- Supabase: Free tier with generous limits
- Railway: PostgreSQL included
- Neon: Serverless PostgreSQL (recommended)
- Amazon RDS: Production-grade AWS hosting
- Email Whitelist: Only emails in
ADMIN_EMAILScan authenticate - Password Hashing: bcrypt with salt rounds
- JWT Sessions: Secure 30-day sessions
- Route Protection: Middleware protects
/admin/*routes - Input Validation: Zod schemas validate all inputs
- CSRF Protection: Built into NextAuth.js
- SQL Injection Prevention: Prisma parameterizes all queries
Important: Change the default password (admin123) immediately after first login!
See CLAUDE.md for detailed architectural guidance.
- Add model to
prisma/schema.prismawithorderfield - Run
npx prisma migrate dev --name add_section_name - Update
app/api/resume/route.ts:- Add to
Promise.all()in GET - Add transaction logic in POST
- Add to
- Create tab component in
app/admin/components/tabs/ - Add tab to
app/admin/page.tsx - Display on public resume page
Images are stored as base64 strings in the database (max 5MB). For larger files or production use, consider:
- Cloudinary: Image CDN with transformations
- AWS S3: Object storage
- Vercel Blob: File storage (recommended for Vercel deployments)
See lib/image-handler.ts for image utilities.
The template uses next-themes with class-based dark mode. Toggle component: components/ThemeToggle.tsx
- Architecture Guide: See
CLAUDE.mdfor detailed technical documentation - API Reference: See route handlers in
app/api/ - Component Library: Shared components in
components/ - Database Schema:
prisma/schema.prisma
# Clear build cache
npm run clean
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install
# Regenerate Prisma Client
npx prisma generate# Reset database (WARNING: deletes all data)
npx prisma migrate reset
# View database in GUI
npx prisma studio
# Check connection
npx prisma db push --skip-generate- Verify
NEXTAUTH_SECRETis set - Check email is in
ADMIN_EMAILS(comma-separated, no spaces) - Clear browser cookies and retry
- Check browser console for errors
- Verify
NEXTAUTH_URLmatches your deployment URL
- Ensure
globals.cssuses@import "tailwindcss"(Tailwind v4 syntax) - All form inputs should have explicit text color:
text-gray-900 - Clear
.nextfolder:npm run clean
Contributions welcome! Please:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with these amazing open-source projects:
- Next.js - React framework
- Tailwind CSS - Utility-first CSS
- Prisma - Next-generation ORM
- NextAuth.js - Authentication
- Framer Motion - Animations
- Lucide - Beautiful icons
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: See
CLAUDE.mdfor technical details
Made with β€οΈ for the developer community
β Star this repo if you find it helpful!