A full-stack event management platform where organizers create events, users discover and book tickets, and admins govern the platform β complete with Stripe payments, Google OAuth, real-time analytics, and Docker-ready deployment.
Note: EventHub was initially developed locally before being uploaded to GitHub. As a full-time student, I typically implement multiple features in focused sessions and commit them together rather than pushing every small change.
- Features
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- Docker Deployment
- Architecture
- API Routes
- Contributing
- License
- Browse and search events by category, location, date, and popularity
- Book tickets with real-time availability tracking
- Secure checkout via Stripe payment integration
- View booking history, download tickets, and manage profile
- Google OAuth and email/password authentication
- Password reset via email
- Create, edit, and delete events with image uploads (Cloudinary)
- Dashboard with revenue analytics, ticket sales charts, and attendee management
- Track event performance with monthly revenue breakdowns
- View detailed attendee lists and individual booking history
- Approve or reject event submissions before they go live
- Platform-wide analytics: users, events, bookings, and revenue
- Manage user accounts β update roles, delete users
- Full oversight of all platform activity
- JWT authentication with HttpOnly cookies (no tokens in localStorage)
- Silent token refresh with automatic retry queue
- Role-based access control across all routes
- Rate limiting, Helmet security headers, and payload size limits
- Graceful shutdown handling for clean deployments
| Layer | Technology |
|---|---|
| Frontend | React 19, React Router 7, Tailwind CSS, Framer Motion, Axios |
| Backend | Node.js β₯20, Express.js, Mongoose ODM |
| Database | MongoDB Atlas |
| Payments | Stripe (Checkout Sessions + Webhooks) |
| Auth | JWT (HttpOnly cookies), Google OAuth 2.0 |
| File Uploads | Cloudinary (via Multer) |
| Nodemailer (SMTP/Gmail) | |
| Logging | Winston + Morgan |
| DevOps | Docker, Docker Compose, Nginx, multi-stage builds |
| Build Tool | Vite 6 |
EventHub/
βββ backend/
β βββ config/ # Database connection
β βββ controllers/ # Route handlers (auth, events, bookings, payments, etc.)
β βββ middleware/ # Auth, error handling, file upload, role checks
β βββ models/ # Mongoose schemas (User, Event, Booking, RefreshToken)
β βββ routes/ # Express route definitions
β βββ utils/ # Logger, email sender, helpers
β βββ server.js # App entry point
β βββ Dockerfile
β βββ .env.example
β βββ package.json
β
βββ frontend/
β βββ src/
β β βββ components/ # Reusable UI components (Navbar, Footer, Cards, etc.)
β β βββ context/ # AuthContext (global auth state)
β β βββ hooks/ # Custom hooks (useAuth, useDeviceDetection, etc.)
β β βββ pages/ # Route pages organized by role
β β β βββ admin/ # Admin dashboard, event approval, user management
β β β βββ auth/ # Login, register, password reset
β β β βββ organizer/ # Organizer dashboard, event CRUD, attendees, analytics
β β β βββ events/ # Event listing, event details
β β β βββ user/ # Profile, tickets
β β β βββ bookings/ # Booking success page
β β βββ services/ # API service layer (axios instances)
β β βββ utils/ # Formatting helpers
β βββ nginx.conf # Production Nginx config
β βββ Dockerfile # Multi-stage build (Node β Nginx)
β βββ .env.example
β βββ package.json
β
βββ docker-compose.yml
βββ README.md
- Node.js β₯ 20.0.0
- npm β₯ 9
- MongoDB (local or MongoDB Atlas)
- Stripe account (for payments β test mode works)
- Cloudinary account (for image uploads)
- Google Cloud project (for OAuth β setup guide)
# 1. Clone the repository
git clone https://github.com/Thabettt/EventHub.git
cd EventHub
# 2. Install backend dependencies
cd backend
npm install
# 3. Install frontend dependencies
cd ../frontend
npm install# 4. Create .env files from examples
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
# 5. Fill in your real values in both .env files
# (see Environment Variables section below)# 6. Start the backend (from /backend)
npm run dev
# 7. Start the frontend (from /frontend β in a separate terminal)
npm run devThe app will be available at:
- Frontend: http://localhost:5173
- Backend API: http://localhost:3003/api
| Variable | Description | Example |
|---|---|---|
PORT |
Server port | 3003 |
NODE_ENV |
Environment mode | development |
FRONTEND_URL |
Frontend origin (CORS + redirects) | http://localhost:5173 |
MONGO_URI |
MongoDB connection string | mongodb://localhost:27017/eventhub |
JWT_SECRET |
Secret key for signing JWTs | (generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))") |
GOOGLE_CLIENT_ID |
Google OAuth client ID | xxxxx.apps.googleusercontent.com |
STRIPE_SECRET_KEY |
Stripe secret key | sk_test_... |
STRIPE_WEBHOOK_SECRET |
Stripe webhook signing secret | whsec_... |
CLOUDINARY_CLOUD_NAME |
Cloudinary cloud name | your_cloud_name |
CLOUDINARY_API_KEY |
Cloudinary API key | 123456789 |
CLOUDINARY_API_SECRET |
Cloudinary API secret | abc123... |
SMTP_HOST |
Email SMTP host | smtp.gmail.com |
SMTP_PORT |
Email SMTP port | 465 |
SMTP_SECURE |
Use TLS | true |
EMAIL_USERNAME |
SMTP email address | you@gmail.com |
EMAIL_PASSWORD |
SMTP app-specific password | xxxx xxxx xxxx xxxx |
| Variable | Description | Example |
|---|---|---|
VITE_API_URL |
Backend API URL (must include /api) |
http://localhost:3003/api |
VITE_GOOGLE_CLIENT_ID |
Google OAuth client ID | xxxxx.apps.googleusercontent.com |
VITE_STRIPE_PUBLIC_KEY |
Stripe publishable key | pk_test_... |
How it connects: The frontend reads
VITE_API_URLfor all API calls. The backend readsFRONTEND_URLfor CORS and redirect URLs. Change the port on one side β update the corresponding URL on the other. One variable per side, everything follows.
β οΈ Never commit.envfiles. Only.env.examplefiles are tracked in git.
The project includes a production-ready, secure Docker configuration. It uses a single-domain architecture where an Nginx reverse proxy serves the frontend and securely routes /api requests to the internal backend container. The backend port is not exposed to the public internet.
# 1. Create a root .env file for docker-compose
cp .env.example .env
# 2. Fill in your real production values in .env
# Keep VITE_API_URL=/api to use the secure Nginx proxy
# FRONTEND_URL must match your actual domain (e.g., https://your-domain.com)
# 3. Build and run
docker-compose up --build -d| Service | Container | Internal Port | Exposed Port | Description |
|---|---|---|---|---|
| Frontend/Proxy | eventhub-frontend |
80 |
80 |
Nginx serving React on / and proxying /api to backend |
| Backend API | eventhub-backend |
3003 |
None π | Express API β completely hidden from the internet |
- Frontend waits for backend health check to pass before starting
- Backend auto-restarts on crash (
unless-stopped) - Frontend uses a multi-stage build: Node.js builds the app β Nginx serves static files
- Nginx handles client-side routing, gzip compression, security headers, and API proxying
# Backend CORS
FRONTEND_URL=https://your-domain.com
# Frontend API Target (Baked into JS bundle)
# Set to /api so requests go to your-domain.com/api and Nginx proxies them
VITE_API_URL=/api- Component-based React with functional components and hooks
- AuthContext provides global auth state with silent token refresh
- Service layer (
services/*.js) β each domain has its own axios instance - Protected routes with role-based guards (
admin,organizer,user) - Smooth animations via Framer Motion and Lenis smooth scrolling
- MVC pattern β models, controllers, and routes are cleanly separated
- Middleware chain: Helmet β Cookie Parser β Rate Limiter β CORS β Morgan β Routes β Error Handler
- Stripe Webhooks β raw body parsing before
express.json()for signature verification - Graceful shutdown β handles
SIGTERM/SIGINT, closes HTTP server and MongoDB connection - Centralized error handler with consistent error response format
Browser β Vite Dev Proxy (/api β :3003) β Express β MongoDB
β Stripe (payments)
β Cloudinary (images)
β Nodemailer (emails)
In production, Nginx replaces the Vite proxy and serves the static frontend bundle.
| Method | Route | Description | Auth |
|---|---|---|---|
POST |
/api/auth/register |
Register a new user | β |
POST |
/api/auth/login |
Login with email/password | β |
POST |
/api/auth/google |
Google OAuth login | β |
POST |
/api/auth/logout |
Logout (clears cookies) | β |
POST |
/api/auth/refresh |
Silent token refresh | β |
POST |
/api/auth/forgot-password |
Send password reset email | β |
PUT |
/api/auth/reset-password/:token |
Reset password | β |
GET |
/api/events |
List events (with filters) | β |
GET |
/api/events/:id |
Get event details | β |
POST |
/api/events |
Create event | Organizer |
PUT |
/api/events/:id |
Update event | Organizer |
DELETE |
/api/events/:id |
Delete event | Organizer |
GET |
/api/events/organizer |
Get organizer's events | Organizer |
PUT |
/api/events/:id/approve |
Approve event | Admin |
PUT |
/api/events/:id/reject |
Reject event | Admin |
POST |
/api/bookings/events/:id |
Book tickets | β |
GET |
/api/bookings/me |
Get user's bookings | β |
GET |
/api/bookings/organizer |
Get organizer's bookings | Organizer |
POST |
/api/payments/create-checkout-session |
Create Stripe session | β |
POST |
/api/payments/webhook |
Stripe webhook handler | β |
GET |
/api/payments/session-status |
Check payment status | β |
GET |
/api/users/me |
Get current user profile | β |
PUT |
/api/users/me |
Update profile | β |
PUT |
/api/users/me/password |
Change password | β |
GET |
/api/users |
List all users | Admin |
PATCH |
/api/users/:id/role |
Update user role | Admin |
DELETE |
/api/users/:id |
Delete user | Admin |
POST |
/api/upload/image |
Upload image to Cloudinary | β |
GET |
/api/admin/dashboard |
Admin dashboard stats | Admin |
GET |
/api/admin/analytics/* |
Platform analytics | Admin |
GET |
/health |
Health check (for load balancers) | β |
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the project
- Create your 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
This project is open source and available under the ISC License.