π₯ ReelSearch is a full-stack web application for discovering movies, TV series, and games through the OMDb catalog and saving them to a personal watchlist backed by PostgreSQL. Users can search the catalog, explore detailed movie metadata, and maintain a persistent watchlist of saved titles.
Frontend:
reelsearch-ten.vercel.app
Backend health check:
reelsearch-api.onrender.com/health
Search results display key movie metadata and allow users to add titles directly to their watchlist.
Hovering over a watchlist item reveals stored metadata including plot, cast, and critic ratings.
- Frontend
- React
- Vite
- React Router
- Tailwind CSS
- Backend
- Node.js
- Express
- Prisma
- Database
- PostgreSQL (Neon)
- Authentication
- bcrypt, JWT (stored in an httpOnly cookie)
- External API
- OMDb API (movie data)
- OpenAI API (natural language watchlist queries)
- Deployment
- Vercel (frontend)
- Render (backend)
π₯ ReelSearch follows a typical full-stack architecture:
- The React + Vite frontend communicates with an Express REST API
- The API handles authentication, search requests, and watchlist management
- Search requests are proxied to the OMDb API, and the server fetches full metadata for each result
- Natural language watchlist queries are parsed using the OpenAI API and converted into structured database filters
- Prisma ORM manages database access for user accounts and watchlists
- Watchlist data is stored in PostgreSQL (Neon)
- Authentication is implemented with JWT tokens stored in secure httpOnly cookies
reelsearch/
ββ client/ # React + Vite frontend
β ββ src/
β β ββ App.jsx
β β ββ pages/
β β β ββ Home.jsx
β β β ββ Login.jsx
β β β ββ Profile.jsx
β β β ββ Register.jsx
β β β ββ Watchlist.jsx
β β ββ components/
β β β ββ SearchBar.jsx
β β ββ services/ # Frontend API wrappers (auth, search, watchlist)
β ββ vite.config.js
β
ββ server/ # Express backend (API, auth, watchlist features)
β ββ index.js # Express entry point
β ββ db.js # Prisma client initialization
β ββ lib/
β β ββ openai.js # OpenAI client setup
β ββ routes/
β β ββ auth.routes.js
β β ββ chat.routes.js # Natural language watchlist queries
β β ββ search.routes.js
β β ββ watchlist.routes.js
β ββ services/
β β ββ omdb.service.js # OMDb API proxy logic
β β ββ chat.service.js
β β ββ watchlistQuery.service.js
β ββ middleware/
β β ββ requireAuth.js # JWT cookie authentication middleware
β ββ utils/
β ββ ratings.util.js
β ββ serializeWatchlistItem.util.js
β
ββ prisma/
β ββ schema.prisma # Prisma schema defining User & Watchlist models
β ββ migrations/ # Generated Prisma migrations
β
ββ package.json # Root scripts for dev / server / client
ββ README.md
Search the OMDb catalog by title and return enriched metadata for each result.
- Results display key information such as poster, title, year, type, and age rating for quick browsing
- The backend fetches full metadata for each unique result before returning it to the client
- Users can add titles directly to their watchlist from the search results
Create an account and securely manage a personal watchlist.
- Users can register and log in with email and password
- Passwords are securely hashed using
bcrypt - Authentication is handled through a signed JWT stored in a secure
httpOnlycookie - Logged-in users can view their email and account creation date via Profile Icon β Profile
Save titles to a personal watchlist backed by PostgreSQL.
- Movies, series, and games can be added directly from search results
- Watchlist items are stored per user using Prisma ORM and PostgreSQL
- Items can be removed from the watchlist at any time
- Hovering over an item reveals expanded metadata including plot, director, cast, and critic ratings
Normalize critic ratings to enable future ranking and sorting features.
- OMDb ratings (IMDb, Rotten Tomatoes, Metacritic) are displayed in their familiar formats (e.g., IMDb: 8.7/10, Rotten Tomatoes: 87%)
- Ratings are normalized internally into comparable scores
- A combined average
sortScoreis computed and stored - These normalized scores are not yet displayed in the UI but will power future ranking and filtering features
- Node.js (version 18 or higher is recommended)
- npm (bundled with Node.js)
- A PostgreSQL database URL (e.g. via Neon, Supabase, local PostgreSQL)
- An OMDb API key (free: https://www.omdbapi.com/apikey.aspx)
- An OpenAI API key (https://platform.openai.com/)
-
Fork or Clone the Repository
git clone https://github.com/abj32/reelsearch.git cd reelsearch -
Install Dependencies
Install backend dependencies:npm install
Then install frontend dependencies:
cd client npm install cd ..
-
Set Up Environment Variables
Create a.envfile in the project root and define:# PostgreSQL connection string used by Prisma DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslmode=require" # Secret key used to sign JWTs JWT_SECRET="a-long-random-string-here" # OMDb API key (used only on the backend) OMDB_API_KEY="your_omdb_api_key_here" # OpenAI API key (used for chat-based watchlist queries) OPENAI_API_KEY="your_openai_api_key_here" # Optional: port for the Express API (default is 5000) PORT=5000
-
Running the Development Server
From the project root run:npm run dev
This uses
concurrentlyto start both- the Express API (
npm run start-server) on http://localhost:5000 - the Vite dev server (
npm run start-client) on http://localhost:5173
- the Express API (
Once npm run dev is running:
- Open the frontend: http://localhost:5173
- Register/Log In
- Note: You do not need to be logged in to search for and view movies/shows/games, but you do need to be logged in to add items to your watchlist
- Click the profile icon in the header and go to Register or Login
- Create an account with email and password or login with an existing account
- After successful registration or login, the server sets an
httpOnlysession cookie (sid) with a signed JWT (expires in 1 hour) - The client automatically fetches your profile on load (
GET /api/auth/profile) to check for session cookie and JWT - You can log out via Profile Icon -> Log out
- Search for Titles
- Use the search bar in the header to search by title
- The frontend calls the backendβs search endpoint (
GET /api/search?q=<query>) - The backend then:
- Calls OMDb using your API_KEY
- Deduplicates results
- Fetches full details for each unique imdbID
- Returns a list of detailed movie objects to the client
- Managing Your Watchlist
- After searching, click the β+β button on a card to add it to your watchlist
- The frontend calls:
POST /api/watchlistwith{ "imdbId": "<imdbID>" }
- The item is stored in your watchlist in the database with a relation to your userId
- Visit the Watchlist page (via Profile Icon -> Watchlist) to see your saved items, view their extra details, and remove them
GET /health
Simple health check:{ "ok": true }
POST /api/auth/register
Body:{ "email": string, "password": string }
Creates a new user, setssidcookie, returns the authenticated userβsid,email, andcreatedAtPOST /api/auth/login
Body:{ "email": string, "password": string }
Verifies credentials, setssidcookie, returns the authenticated userβsid,email, andcreatedAtPOST /api/auth/logout
Clears thesidcookieGET /api/auth/profile
Requires auth (requireAuthmiddleware) Returns the authenticated userβsid,email, andcreatedAt
GET /api/search?q=<query>
Calls OMDb using the backendβs API_KEY, deduplicates results, and returns an array of detailed movie objects
Note: All watchlist routes require authentication (requireAuth middleware)
GET /api/watchlist
Returns the current user's watchlist itemsPOST /api/watchlist
Body:{ "imdbId": string }- Fetches full details from OMDb
- Normalizes ratings
- Stores the item for the current user
DELETE /api/watchlist/:imdbId- Removes specific item from the userβs watchlist
Note: Requires authentication (requireAuth middleware)
-
POST /api/chat/watchlist
Body:{ "message": string }- Parses natural language input using OpenAI
- Converts the request into structured filters and sorting options
- Returns filtered/sorted watchlist items
Example:
{ "message": "show my sci-fi movies after 2015" }
- π Watchlist sorting/ranking
- Add options to sort by critic ranking using the stored normalized rating scores (
imdbScore,rtScore,mcScore,sortScore)
- Add options to sort by critic ranking using the stored normalized rating scores (
- π― Filtering
- Filter watchlist by type (movie / series / game)
- π Issue-driven refinements:
- Smaller UX and styling improvements tracked under the Issues tab.
Stay tuned for updates!
MIT

