A full-stack platform that gives startup founders and early-stage teams exclusive deals on SaaS products (cloud, marketing, analytics, productivity). Some deals are public; others are locked and require user verification to claim.
backend/? Node.js + Express + MongoDB (Mongoose). REST API, JWT auth.frontend/? Next.js (App Router), TypeScript, Tailwind CSS, Framer Motion.
Backend and frontend are separate folders and run as separate processes.
- Node.js 18+
- MongoDB (local or Atlas)
cd backend
npm install
cp .env.example .env # edit .env if needed (MONGODB_URI, JWT_SECRET)
npm run devBackend runs at http://localhost:5000.
Seed sample deals (optional):
npm run seedcd frontend
npm install
# Optional: create .env.local with NEXT_PUBLIC_API_URL=http://localhost:5000/api
npm run devFrontend runs at http://localhost:3000.
Prerequisites: MongoDB running, backend running with latest code (cd backend && npm run dev), and deals seeded (npm run seed in backend). The backend CORS allows http://127.0.0.1:3000 (used by Playwright)?restart the backend if you just updated the repo.
cd frontend
npm install
npx playwright install chromium # one-time: install browser
npm run test:e2ePlaywright starts the frontend dev server automatically. The tests cover: landing page, register/login, deals listing and detail, claim flow, and dashboard. For UI mode: npm run test:e2e:ui.
- User opens the app ? sees Landing (hero, value prop, CTA).
- Register / Log in ? backend creates/validates user, returns JWT. Frontend stores token and shows Dashboard link.
- Browse deals (
/deals) ? frontend callsGET /api/deals(optional filters: category, access). Deals list with locked/unlocked indication. - Deal detail (
/deals/[id]) ?GET /api/deals/:id. User sees full description, partner, eligibility. Claim button callsPOST /api/deals/:id/claimwith JWT. - Claim flow ? see below.
- Dashboard (
/dashboard) ?GET /api/claimswith JWT. Shows profile and list of claimed deals with status (pending / approved / rejected).
- Registration:
POST /api/auth/register(name, email, password). Backend hashes password (bcrypt), creates user, returns JWT. - Login:
POST /api/auth/login(email, password). Backend validates, returns JWT. - JWT: Signed with
JWT_SECRET, containsid(user id). Expiry: 7 days. - Protected routes:
POST /api/deals/:id/claim,GET /api/claims,GET /api/auth/me. Request must include header:Authorization: Bearer <token>. Middleware verifies JWT and attachesreq.user. - Locked deals: Backend checks
deal.isLockedanduser.isVerified. If deal is locked and user is not verified ? 403 with message that verification is required. Unverified users cannot claim locked deals.
- User clicks Claim on deal detail page.
- Frontend sends
POST /api/deals/:id/claimwithAuthorization: Bearer <JWT>. - Backend:
- Verifies JWT ? gets user.
- Loads deal by id; if not found ? 404.
- If
deal.isLocked && !user.isVerified? 403 (verification required). - If user already has a claim for this deal ? 400 (already claimed).
- Creates Claim document (user, deal, status:
pending). - Returns created claim (with populated deal).
- Frontend shows success (e.g. ?Claimed! Check your dashboard.?). User can go to Dashboard to see claimed deals and status.
- API base URL: Frontend uses
NEXT_PUBLIC_API_URL(defaulthttp://localhost:5000/api). - Auth: Frontend stores JWT in
localStorageand sends it inAuthorization: Bearer <token>for protected calls. - CORS: Backend allows origin
FRONTEND_URLorhttp://localhost:3000. - Data: All deal and claim data comes from backend (MongoDB). Frontend does not implement its own persistence for deals/claims.
- Verification:
user.isVerifiedexists but there is no in-app flow to verify users (e.g. admin panel or integration). For demo, users can be set to verified manually in DB. - JWT in localStorage: Vulnerable to XSS. For production, consider httpOnly cookies.
- No rate limiting on auth or claim endpoints.
- No email verification on signup.
- Deal validity:
validUntilexists on Deal but is not enforced when claiming.
- Move JWT to httpOnly cookies and use CSRF protection.
- Add rate limiting (e.g. express-rate-limit) on
/authand/deals/:id/claim. - Implement user verification flow (e.g. admin approval, or automated checks).
- Input validation with a schema library (e.g. Joi/Zod) and sanitization.
- Logging and error tracking (e.g. Pino, Sentry).
- Env validation at startup (required env vars).
- HTTPS and secure headers (helmet).
- Tests: unit and integration for auth, deals, and claims.
- Animations: Landing uses Framer Motion (hero, sections, cards). Deals listing uses stagger and layout transitions. Loading states use skeletons.
- Responsiveness: Layouts are responsive (Tailwind breakpoints). Header, forms, and deal cards work on mobile.
- Loading: Skeleton placeholders on deals list and dashboard; disabled buttons and ?Claiming...? during claim.
- Accessibility: Semantic HTML, labels on form inputs. Further: focus states, ARIA where needed, keyboard navigation.
- Performance: Next.js App Router for routing and code splitting. Consider image optimization if partner logos are added.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/auth/register |
No | Register (name, email, password) |
| POST | /api/auth/login |
No | Login (email, password) |
| GET | /api/auth/me |
Yes | Current user |
| GET | /api/deals |
No | List deals (query: category, access) |
| GET | /api/deals/:id |
No | Single deal |
| POST | /api/deals/:id/claim |
Yes | Claim deal |
| GET | /api/claims |
Yes | Current user?s claims |
MIT (or as specified for the assignment).