A full-stack Netflix clone built with the MERN stack. It uses the TMDB API for movie/TV data, JWT cookie-based authentication, search with history, trailers, and a responsive Netflix-style UI.
https://ministream-gg.netlify.app/
ℹ️ The live demo hosts the frontend only, so the UI is fully browsable but sign-up / login / movie data need the backend. Run the project locally (see Run locally) for the complete experience.
| Layer | Tech |
|---|---|
| Frontend | React 18, Vite, Tailwind CSS, Zustand, React Router, Axios |
| Backend | Node.js, Express, MongoDB (Mongoose), JWT, bcrypt |
| Data | TMDB API |
- Sign up / log in / log out with JWT stored in an httpOnly cookie
- Browse trending movies & TV shows by category
- Watch trailers, see similar titles and details
- Search movies, TV shows and people (with search history)
- Protected API routes
.
├── backend/ # Express API (auth, movies, tv, search)
│ ├── config/ # db + env config
│ ├── controller/ # route handlers
│ ├── middleware/ # protectRoute (JWT auth)
│ ├── models/ # Mongoose models
│ ├── routes/ # API routes (/api/v1/...)
│ └── server.js # app entry point
├── frontend/ # React + Vite app (builds to frontend/dist)
├── netlify.toml # Netlify config (frontend-only deploy)
├── .env.example # template for required env vars
└── package.json # backend scripts + the production build script
- Node.js 18 or newer
- A free MongoDB Atlas database (or local MongoDB)
- A free TMDB API account
Create a .env file in the project root (copy from .env.example):
| Variable | Description |
|---|---|
MONGO_ID |
MongoDB connection string |
PORT |
Backend port (default 5000) |
JWT_SECRET |
Long random string used to sign auth tokens |
NODE_ENV |
development or production |
TMDB_API_KEY |
TMDB API Read Access Token (v4 auth, sent as a Bearer token) |
The
.envfile is git-ignored — never commit your real secrets.
The Vite dev server runs the UI on port 5173 and proxies /api requests
to the backend on port 5000 (see frontend/vite.config.js).
# 1. Backend (project root)
npm install
npm run dev # starts Express with nodemon on http://localhost:5000
# 2. Frontend (in a second terminal)
cd frontend
npm install
npm run dev # starts Vite on http://localhost:5173Open http://localhost:5173.
This builds the frontend and lets Express serve both the API and the static React build from one port.
# from the project root
npm run build # installs deps + builds frontend/dist
npm start # serves everything on http://localhost:5000Open http://localhost:5000 (make sure NODE_ENV=production in .env).
This repo includes a netlify.toml that deploys only the React frontend.
- Push this repo to GitHub.
- On Netlify → Add new site → Import from Git.
- Pick this repo. The build settings come from
netlify.toml:- Base directory:
frontend - Build command:
npm run build - Publish directory:
dist
- Base directory:
- Deploy.
⚠️ Important: Netlify can only host static files — it does not run the Express server. So on the deployed Netlify site the UI will load and look correct, but logging in and loading movies will not work until you also host the backend (see below). To use the app fully, run it locally with the steps above.
Netlify hosts the frontend; the Express backend needs a Node host. Two ways:
Easiest — host the whole app on one Node host (recommended).
Because npm run build + npm start already serve the frontend and API
together, you can deploy the entire repo to Render,
Railway or Fly.io:
- Build command:
npm run build - Start command:
npm start - Add the same env vars from
.env, withNODE_ENV=production
Keep the frontend on Netlify + backend elsewhere.
- Deploy the backend to Render/Railway → you get a URL like
https://your-backend.onrender.com. - Make the Netlify frontend talk to it. Either:
- Proxy (simplest): uncomment the
/api/*redirect block innetlify.tomland point it at your backend URL. The frontend keeps using relative/apicalls and cookies stay same-origin. or - Direct: set
axios.defaults.baseURLfrom aVITE_API_URLenv var, enable CORS on the backend withcredentials: trueand the Netlify origin, and set the auth cookie withsameSite: "none"andsecure: truein production.
- Proxy (simplest): uncomment the
- In Netlify → Site settings → Environment variables, add any
VITE_*vars you introduced (Vite only exposes vars prefixed withVITE_).
Port 5000 already in use (Windows):
netstat -ano | findstr :5000 # find the PID using the port
taskkill /PID <pid> /F # kill it- Movie & TV data provided by The Movie Database (TMDB). This product uses the TMDB API but is not endorsed or certified by TMDB.
- Built by Shreyansh Gupta.
- Deployment configuration and documentation assisted by Claude Code.
Released under the terms of the LICENSE file in this repository.