Professional photography event management platform. Book photographers, manage events, track orders, and run your photography business.
- Frontend: React 18 (Create React App) with custom CSS design system
- Backend: Express.js REST API with JWT authentication
- Database: MySQL / MariaDB
- Email: Nodemailer with Gmail
- Node.js 18+
- MySQL / MariaDB running locally
- npm
Import the schema into your MySQL server:
mysql -u root -p < db/photodb.sqlcd be
cp .env.example .env # Edit .env with your values
npm install
npm run server # Starts on port 8801cd fe
npm install
npm start # Starts on port 3000cd be
npm start # Runs backend + frontend concurrently| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 8801 |
Server port |
DB_HOST |
No | localhost |
MySQL host |
DB_USER |
No | root |
MySQL user |
DB_PASSWORD |
No | (empty) | MySQL password |
DB_NAME |
No | photodb |
Database name |
JWT_SECRET |
Yes (production) | dev-only random | Token signing secret |
EMAIL_USER |
Yes | - | Gmail address for sending emails |
EMAIL_PASS |
Yes | - | Gmail App Password |
ADMIN_EMAILS |
No | - | Comma-separated admin notification emails |
SITE_URL |
No | http://localhost:3000 |
Frontend URL (used in email links) |
API_BASE_URL |
No | http://localhost:8801 |
Public API URL (used for image URLs) |
GOOGLE_CLIENT_ID |
No | - | Google OAuth client ID |
| Variable | Required | Default | Description |
|---|---|---|---|
REACT_APP_API_URL |
No | http://localhost:8801 |
Backend API URL |
REACT_APP_GOOGLE_CLIENT_ID |
No | - | Google OAuth client ID |
REACT_APP_GOOGLE_MAPS_KEY |
No | - | Unused for address/venue (manual text entry only) |
| Role ID | Name | Access |
|---|---|---|
| 1 | Admin | Full dashboard, orders, reports, workers, content management |
| 2 | Customer | Create orders, view own orders, profile, gallery |
| 3 | Photographer-Stills | View assigned events, profile, gallery |
| 4 | Photographer-Video | View assigned events, profile, gallery |
- Sign up as Customer
- Create a new order (select event type, package, venue as free text, date/time)
- Receive order confirmation email
- Track order status (Pending / Approved / Rejected)
- View order history with date filtering
- Sign in as Admin
- View orders on calendar by date
- Assign photographers to events
- Approve or reject orders
- Manage workers and customers
- Generate reports (revenue, expenses, customers, workers, orders)
- Upload/manage gallery images
- Manage FAQ and About Us content
- Sign in as Photographer
- View assigned events
- Receive email notifications for new assignments
- Go to Google Cloud Console
- Create a new project
- Enable "Google Identity Services" API
- Go to Credentials > Create OAuth 2.0 Client ID (Web application)
- Add authorized JavaScript origins:
http://localhost:3000(development)https://yourdomain.com(production)
- Copy the Client ID
- Set
GOOGLE_CLIENT_IDinbe/.env - Set
REACT_APP_GOOGLE_CLIENT_IDinfe/.env - Restart both servers
Note: Google login only works for users who already have a PhotoClick account. Users must sign up with email/password first.
- JWT-based authentication with 24h token expiry
- bcrypt password hashing (backward-compatible upgrade from plaintext)
- Role-based access control on all protected endpoints
- IDOR protection (users can only access their own data)
- Rate limiting on auth endpoints (20 req/15min) and API (300 req/15min)
- Helmet security headers
- CORS restricted to frontend origin
- File upload validation (type, size, count limits)
- Input validation on all endpoints
- Secure password reset flow
- No secrets in source code (environment variables only)
cd be
npm install --production
NODE_ENV=production node app.jsUse PM2 for process management:
npm install -g pm2
pm2 start app.js --name photoclick-apicd fe
npm run buildServe the build/ folder with nginx or any static file server.
- Set a strong, random
JWT_SECRET(32+ characters) - Set strong MySQL credentials (not root/empty)
- Configure HTTPS on both frontend and backend
- Update
SITE_URLto production frontend URL - Update
REACT_APP_API_URLto production backend URL - Set
API_BASE_URLto public backend URL -
REACT_APP_GOOGLE_MAPS_KEYis optional (address fields use manual text entry) - Configure Gmail App Password for email
- Set up database backups
- Ensure
.envfiles are NOT in version control - Set
NODE_ENV=productionon the server
Manual and API testing materials for this project live under qa/. They are written for a Junior QA Tester portfolio (sample cases and reports — not a claim of professional QA employment).
| Document | Description |
|---|---|
| qa/README.md | QA pack overview and index |
| qa/test-plan.md | Scope, strategy, environments, entry/exit criteria |
| qa/test-cases.md | 80+ detailed manual test cases with IDs and priorities |
| qa/bug-reports.md | Sample defect reports for portfolio use |
| qa/api-test-scenarios.md | API scenarios aligned with be/routes/api.js |
| qa/traceability-matrix.md | Requirements ↔ test case mapping |
| qa/postman/photoclick-api-collection.json | Postman Collection v2.1 |
The QA pack includes:
- 80+ manual test cases
- Sample bug reports
- API test scenarios
- Traceability matrix
- Postman collection
- Coverage for authentication, booking flow, admin order management, role-based access, gallery, reports, form validation, manual address input (no Google autocomplete), Israel-local booking date validation, and booking success message after submit
Recent UI behavior documented in QA (no backend or database changes required to retest):
- Address / venue: free-text on New Booking, Sign up, and Profile — Google Places / Maps autocomplete removed
- Booking dates: today or future in Israel local time; booking does not use the Reports “Year 2000–2100” message
- Gallery: placeholder for broken or missing images
- Booking success: after a successful
createOrderresponse, customers see: “Your booking request was submitted successfully and is now pending approval.”
All rights reserved. PhotoClick.