Skip to content

abj32/reelsearch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

113 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ReelSearch

ReelSearch is a full-stack web application for discovering movies, TV series, and games through the OMDb catalog. Users can search the catalog, sort and filter results by rating, type, and year, explore detailed metadata with aggregated critic scores, and maintain a persistent personal watchlist.


Live Demo

Frontend:
reelsearch-ten.vercel.app

Backend health check:
https://reelsearch-api-f3qb.onrender.com/health

⚠️ Note: The app may take ~20–30 seconds to respond on the first request after inactivity because the server runs on Render's free tier.


Screenshots

Search Results

Search results display key movie metadata and allow users to add or remove titles from their watchlist.


Watchlist

Saved titles are displayed in a poster grid with sort and filter controls. Items can be removed or opened for full details.


Item Detail

Clicking any poster card opens a full detail overlay with plot, cast, director, and critic scores from IMDb, Rotten Tomatoes, and Metacritic.


Profile

The profile page displays account info alongside watchlist stats computed from saved titles.


Tech Stack

  • Frontend
    • React
    • Vite
    • React Router
    • Tailwind CSS v4
  • 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)

System Architecture

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

Project Structure

reelsearch/
├─ client/                  # React + Vite frontend
│  ├─ src/
│  │  ├─ App.jsx
│  │  ├─ index.css          # Tailwind v4 theme tokens and global styles
│  │  ├─ pages/
│  │  │  ├─ Home.jsx
│  │  │  ├─ Login.jsx
│  │  │  ├─ Profile.jsx
│  │  │  ├─ Register.jsx
│  │  │  └─ Watchlist.jsx
│  │  ├─ components/
│  │  │  ├─ AuthForm.jsx    # Shared login/register form
│  │  │  ├─ Dropdown.jsx    # Accessible sort/filter dropdown
│  │  │  ├─ ItemDetail.jsx  # Full-screen detail overlay
│  │  │  ├─ MediaGrid.jsx   # Shared poster grid with sort/filter toolbar
│  │  │  ├─ PosterCard.jsx  # Individual poster card with rating badge
│  │  │  ├─ SearchBar.jsx
│  │  │  └─ WatchlistChat.jsx
│  │  ├─ utils/
│  │  │  ├─ mediaHelpers.js  # Sort/filter logic and rating derivation
│  │  │  └─ normalizeMovie.js # Shapes watchlist API responses for the UI
│  │  └─ services/           # Frontend API wrappers (auth, search, watchlist)
│  ├─ vercel.json           # Rewrites /api/* to the Render backend in production
│  └─ 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/
│     ├─ normalizeSearchResult.js  # Normalizes OMDb search results before sending to client
│     ├─ 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

Features

🔍 Movie / Show / Game Search

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
  • Results can be sorted by relevance, rating, title, or release year, and filtered by content type (Movies, Series, or Games)
  • Clicking a poster card opens a detail overlay with plot, director, cast, and individual scores from IMDb, Rotten Tomatoes, and Metacritic
  • Users can add titles directly to their watchlist from the search results

👤 User Accounts & Authentication

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 httpOnly cookie
  • Logged-in users can view their profile via the avatar icon in the header → Profile, which shows their email, member since date, and watchlist stats
  • The profile page displays watchlist stats computed from saved titles: total items, composite average rating, and a breakdown by Movies, Series, and Games

📺 Persistent Watchlist

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 Clicking a poster card opens a detail overlay with plot, director, cast, and critic ratings
  • Watchlist items can be sorted and filtered using the same controls as search results
  • A built-in assistant lets users filter and sort their watchlist using plain-English queries such as "show my sci-fi movies after 2015," powered by the OpenAI API

⭐ Ratings & Normalization

Normalize critic ratings from multiple sources into a single comparable score.

  • OMDb ratings (IMDb, Rotten Tomatoes, Metacritic) are normalized to a 0–100 scale and averaged into a composite sortScore
  • The composite score is displayed as a star badge (0–10) on every poster card
  • Individual scores from all three sources are shown in full inside the item detail overlay
  • The sortScore also powers the "Rating" sort option on both the search results and watchlist grids

Getting Started

Prerequisites

Installation and Setup

  1. Fork or Clone the Repository

    git clone https://github.com/abj32/reelsearch.git
    cd reelsearch
  2. Install Dependencies
    Install backend dependencies:

    npm install

    Then install frontend dependencies:

    cd client
    npm install
    cd ..
  3. Set Up Environment Variables
    Create a .env file 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
    
    # Optional: set on your Render backend to allow requests from your production frontend
    CLIENT_URL="https://your-frontend.vercel.app"
    
    # Optional: set on your Render backend to allow Vercel preview deployment URLs
    # Use a regex matching your preview URL pattern, e.g. "https://reelsearch-.*\.vercel\.app"
    VERCEL_PREVIEW_ORIGIN_REGEX="your-regex-here"
  4. Running the Development Server
    From the project root run:

    npm run dev

    This uses concurrently to start both


Using the App

Once npm run dev is running:


  1. 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 httpOnly session 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
  1. 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
    • Normalizes ratings from IMDb, Rotten Tomatoes, and Metacritic into a composite score
    • Returns a list of enriched movie objects to the client
  1. Managing Your Watchlist
  • After searching, click the “+” button on a card to add it to your watchlist; saved titles show a trash icon that removes them from your watchlist
  • The frontend calls:
    • POST /api/watchlist with { "imdbId": "<imdbID>" }
  • The item is stored in your watchlist in the database with a relation to your userId
  • Visit the Watchlist page via the bookmark icon in the header to browse saved items, view full details, and remove titles

API Overview (Backend routes)

Error responses

API errors return a consistent JSON shape:

{
  "code": "MACHINE_READABLE_ERROR_CODE",
  "message": "Human-readable error message"
}

Health

  • GET /health
    Simple health check: { "ok": true }

Auth ( /api/auth )

  • POST /api/auth/register
    Body: { "email": string, "password": string }
    Creates a new user, sets sid cookie, returns the authenticated user’s id, email, and createdAt
  • POST /api/auth/login
    Body: { "email": string, "password": string }
    Verifies credentials, sets sid cookie, returns the authenticated user’s id, email, and createdAt
  • POST /api/auth/logout
    Clears the sid cookie
  • GET /api/auth/profile
    Requires auth (requireAuth middleware) Returns the authenticated user’s id, email, and createdAt

Search ( /api/search )

  • GET /api/search?q=<query>
    Calls OMDb using the backend's API_KEY, deduplicates results, fetches full metadata for each unique result, normalizes ratings into a composite sortScore, and returns an array of enriched movie objects

Watchlist ( /api/watchlist )

Note: All watchlist routes require authentication (requireAuth middleware)

  • GET /api/watchlist
    Returns the current user's watchlist items
  • POST /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

Chat ( /api/chat )

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" }

Roadmap & Upcoming Updates

  • 🤖 AI-Powered Content Discovery
    • Discover movies, TV series, and games using natural language prompts
    • Receive personalized recommendations based on genres, themes, actors, directors, moods, and viewing preferences
    • Examples:
      • "Recommend a sci-fi movie like Interstellar"
      • "What are some suspenseful mystery series?"
      • "Suggest a comedy that's good for family movie night"
  • Watchlist Insights & Recommendations
    • Leverage stored metadata and normalized critic scores for smarter ranking and recommendation features
  • 📝 Issue-driven refinements:
    • Smaller UX and styling improvements tracked under the Issues tab.

Stay tuned for updates!


License

MIT

About

Full-stack movie discovery and watchlist app built with React, Express, Prisma, and PostgreSQL.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors