A modern, professional CV website built with React and Node.js, featuring visitor analytics, PDF export, and containerized deployment.
- β¨ Modern Professional Design - Clean, readable layout with no bright colors
- π PDF Export - Download CV as PDF with one click
- π Visitor Analytics - Track page views, unique visitors, and access patterns
- πΌοΈ Profile Picture Upload - Easy profile picture management
- π± Responsive Design - Works perfectly on all devices
- π³ Containerized - Ready for Docker deployment
- β‘ Easy Updates - JSON-based CV data for quick modifications
- Install All Dependencies
This will install dependencies for the main project, server, and client.
npm run setup
-
Start Development Server
npm run dev
-
Access the Application
- CV Website: http://localhost:3000
- Backend API: http://localhost:3001
- Analytics Dashboard: http://localhost:3000/admin
-
Development with Docker
docker-compose --profile dev up
-
Production with Docker
docker-compose up cv-website
-
Production with Nginx (for custom domains)
# Copy environment template cp .env.example .env # Edit .env with your domain # DOMAIN=yourdomain.com # Start with nginx reverse proxy docker-compose --profile production up
If the automatic setup doesn't work:
# Install main dependencies
npm install
# Install server dependencies
cd server
npm install
# Install client dependencies
cd ../client
npm install
# Go back to root
cd ..
# Start development
npm run dev- Default: Just the CV website (port 3001)
- dev: Development mode with hot reload (ports 3000 + 3001)
- production: Full production setup with Nginx reverse proxy (ports 80 + 443)
-
Netlify (Recommended)
- Free domain:
stefan-cv.netlify.app - Free hosting + CI/CD
- Easy custom domain setup
- Free domain:
-
Vercel
- Free domain:
stefan-cv.vercel.app - Automatic deployments from Git
- Free domain:
-
GitHub Pages
- Free domain:
stefanclaassen.github.io - Perfect for static sites
- Free domain:
-
Freenom
- Extensions:
.tk,.ml,.ga,.cf - 12 months free
- Extensions:
-
GitHub Pages Custom
- Use your repository name as subdomain
# Build the client
cd client
npm run build
# Deploy build folder to Netlify
# Or connect GitHub repository for auto-deployment# Set your domain
echo "DOMAIN=yourdomain.com" > .env
# Build and start
docker-compose --profile production up -d
# Your site will be available at:
# http://yourdomain.com (port 80)
# https://yourdomain.com (port 443, if SSL configured)# On your server
git clone <your-repo>
cd CV
# Production build
docker-compose up cv-website -d
# Or with custom domain
docker-compose --profile production up -dFor production with custom domain:
-
Create SSL directory
mkdir ssl
-
Get SSL certificates (Let's Encrypt recommended)
# Using certbot sudo certbot certonly --standalone -d yourdomain.com # Copy certificates cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem ssl/cert.pem cp /etc/letsencrypt/live/yourdomain.com/privkey.pem ssl/key.pem
-
Update nginx.conf - Uncomment HTTPS section
-
Restart services
docker-compose --profile production restart
stefan-cv/
βββ client/ # React frontend
β βββ src/
β β βββ components/
β β β βββ CVPage.js # Main CV display
β β β βββ AdminPage.js # Analytics dashboard
β β βββ App.js # Main React app
β β βββ App.css # Styling
β βββ public/
βββ server/ # Node.js backend
β βββ index.js # Express server
β βββ cv-data.json # CV content (easily editable)
β βββ package.json
βββ data/ # SQLite database
βββ uploads/ # Profile pictures
βββ nginx.conf # Nginx reverse proxy config
βββ .env.example # Environment template
βββ Dockerfile
βββ docker-compose.yml
βββ README.md
- Real-time Tracking: Every page visit is logged with IP, timestamp, user agent, and referrer
- Dashboard: View total visits, unique visitors, daily statistics, and recent visitor details
- Privacy-Focused: Only essential data is collected for analytics
- High Quality: Uses html2canvas and jsPDF for professional PDF generation
- Responsive: Automatically handles page breaks and formatting
- Branded: Maintains visual design and styling in PDF format
Edit server/cv-data.json to update CV content:
{
"personalInfo": {
"name": "Your Name",
"title": "Your Title",
"email": "your.email@example.com"
},
"experience": [...],
"skills": [...]
}- Upload via admin dashboard at
/admin - Automatic image optimization and validation
- Secure file handling with size limits
GET /api/cv-data- Retrieve CV contentPOST /api/cv-data- Update CV contentPOST /api/track-visit- Log visitor analyticsGET /api/analytics- Get visitor statisticsPOST /api/upload-picture- Upload profile picture
DOMAIN- Your domain name (default: localhost)PORT- Server port (default: 3001)NODE_ENV- Environment mode (development/production)
- Rate limiting on API endpoints
- File upload validation and size limits
- CORS protection
- Helmet.js security headers
- Nginx reverse proxy for production
-
'concurrently' is not recognized
npm install # or npm run setup -
Docker nginx.conf error
- Make sure
nginx.confexists in project root - Check file permissions
- Make sure
-
Ports already in use
- Kill processes using ports 3000, 3001, 80, 443
- Or change ports in docker-compose.yml
-
SSL certificate errors
- Ensure certificates exist in
ssl/directory - Check certificate permissions
- Verify nginx.conf SSL configuration
- Ensure certificates exist in
- CV Updates: Edit JSON file and restart server
- Picture Updates: Use admin dashboard upload feature
- Analytics: Monitor via
/admindashboard - Backups: Regularly backup
data/folder containing visitor database
MIT License - Feel free to use this project as a template for your own CV website.


