⚠️ ARCHIVED PROJECT: This repository is no longer maintained. The application has been fully migrated to Next.js for improved performance, Server-Side Rendering (SSR), and modern architecture.👉 View the active, updated version here: moviemon-nextJS
MovieMon is an open-source movie discovery and personal library experience that helps users explore large catalogs, apply rich filters, and keep track of what they want to watch or have already watched. The current implementation includes account management, email-based auth flows, subtitle support, and a role-based admin stats dashboard.
- Discover movies fast with search, filters, trending lists, and infinite scroll
- Personal library features for saved, watch later, and watch history
- Account flows for signup, login, email verification, password reset, and profile updates
- Avatar uploads and account settings backed by Cloudinary
- Role-based admin dashboard for platform and library stats
- Media playback with subtitle support for a complete viewing experience
- Clear loading, empty, and error states for smooth UX
- Responsive, performance‑minded UI built for long sessions
Client
- React 19 + Vite
- React Router
- TanStack Query
- Tailwind CSS
- MUI (Material UI)
- Framer Motion
- Swiper
- HLS.js + Plyr
- Lottie
Server
- Node.js + Express
- MongoDB + Mongoose
- JWT auth + bcrypt with role-based access control
- Multer (uploads) + Cloudinary
- EmailJS (verification and password reset flows)
- Helmet, CORS, Morgan
- Winston logging
Tooling
- ESLint (boundaries + import rules)
- Jest + Supertest + mongodb-memory-server
MovieMon follows a feature-based structure inspired by FSD principles, with strict layer boundaries enforced by ESLint. The goal is a clear, predictable dependency graph and a clean separation between app shell, domain features, and shared primitives.
Frontend folders in client/src:
app: App shell (root layout, providers, routing)pages: Route-level screens (orchestrate features and widgets)features: Domain logic grouped by feature (no cross-feature imports)widgets: Feature-aware compositions used by pages/featuresshared: Global UI primitives, hooks, utils, data, assets, styles
Backend folders in server/src:
modules: Feature modules (controller ? service ? repository)app,config,middlewares,shared,tests
flowchart TD
User["User"] --> Page
subgraph Frontend
AppShell["App Shell"]
Page["Pages"]
Feature["Features"]
Widgets["Widgets"]
Shared["Shared"]
API["API Layer"]
end
subgraph Backend
Router["Router"]
Controller["Controller"]
Service["Service"]
Repository["Repository"]
DB[("Database")]
External["External Services"]
end
AppShell --> Page
Page --> Feature
Page --> Widgets
Feature --> Widgets
Page --> Shared
Feature --> Shared
Widgets --> Shared
API -->|"HTTP Request"| Router
Router --> Controller
Controller --> Service
Service --> Repository
Repository --> DB
Service --> External
DB --> Repository
Repository --> Service
Service --> Controller
Controller -->|"JSON Response"| API
API --> Page
appis the shell and should be the top of the tree.pagescan access:features,widgets, andshared.featurescan access:widgetsandshared.widgetscan access:featuresandshared.sharedmust not import fromfeatures,widgets,pages, orapp.- No cross-feature imports inside
features.
These rules are enforced via ESLint (eslint-plugin-boundaries and import/no-restricted-paths).
- Node.js >= 18
- npm >= 9
# from repo root
cd client
npm install
cd ../server
npm installCreate .env files as needed. Only include the variables your deployment requires.
Client (client/.env)
VITE_SERVER_BASE_URL=http://localhost:3000
VITE_HLS_PROXY_URL=http://localhost:3000Server (server/.env)
NODE_ENV=development
PORT=3000
MONGO_URI=...
JWT_SECRET=...
JWT_EXPIRES_IN=7d
LOG_LEVEL=info
MOVIES_API_PROVIDER=tmdb
MOVIES_API_BASE_URL=...
MOVIES_API_KEY=...
OPEN_SUBTITLES_API_BASE_URL=...
OPEN_SUBTITLES_API_KEY=...
OPEN_SUBTITLE_USERNAME=...
OPEN_SUBTITLE_PASSWORD=...
SUBDL_API_BASE_URL=...
SUBDL_API_KEY=...
SUBTITLES_API_KEY_MODE=bearer
EMAILJS_SERVICE_ID=...
EMAILJS_TEMPLATE_ID=...
EMAILJS_PUBLIC_KEY=...
EMAILJS_PRIVATE_KEY=...
CLOUDINARY_CLOUD_NAME=...
CLOUDINARY_API_KEY=...
CLOUDINARY_API_SECRET=...
APP_BASE_URL=...# terminal 1
cd server
npm run dev
# terminal 2
cd client
npm run devBase URL: /api
Health
GET /api/health
Auth
POST /api/auth/registerPOST /api/auth/loginGET /api/auth/verifyPOST /api/auth/verify/resendGET /api/auth/email-change/approvePOST /api/auth/password/forgotPOST /api/auth/password/reset
Movies
GET /api/movies/video-srcGET /api/movies/*(proxy to provider)
Subtitles (requires auth)
GET /api/subtitles/list/:mediaIdGET /api/subtitles/file/:mediaId
Users
PATCH /api/users/me(auth, multipart avatar)DELETE /api/users/me(auth)GET /api/users/saved(auth)GET /api/users/watchlater(auth)GET /api/users/watch-history(auth)POST /api/users/saved/:movieId(auth)POST /api/users/watchlater/:movieId(auth)POST /api/users/watch-history/:movieId(auth)
Admin (auth + admin role)
GET /api/admin/stats
Client (client/package.json)
npm run dev— start Vite dev servernpm run build— production buildnpm run preview— preview production buildnpm run lint— lint codebase
Server (server/package.json)
npm run dev— start server with nodemonnpm start— start servernpm test— run tests
See Privacy Policy for details.
See Terms of Use for details.
Please see CONTRIBUTING for guidelines.
MIT License. See LICENSE for details.
- Portfolio: https://developer-rayhan.netlify.app
- GitHub: https://github.com/rayhan5497