Cineverse is a modern, high-performance, and beautifully designed movie search and recommendation engine. It curates custom film recommendations using content-based machine learning algorithms.
Built with a FastAPI backend and a React + Vite frontend, Cineverse calculates metadata-based vector similarities to instantly match search queries and profiles. In production, it leverages a smart precomputed lookup system to bypass Vercel's serverless size constraints, offering sub-millisecond query responses.
- Content-Based Recommendations: Recommends movies by calculating exact vector affinities based on title, genres, release year, and descriptive tags.
- Dynamic Discover Console: Filter the movie catalog interactively by selecting specific genres, restricting release year ranges, and establishing minimum IMDb rating thresholds.
- Instant Live Search & Autocomplete: Prefix-matching query execution provides suggestions in real-time as you type.
- Personalization & Offline Persistency: Track movie watchlists and submit custom reviews, securely persisted on the client side using browser Local Storage.
- Analytics Dashboard: Clean, responsive visualizations detailing user history, including genre distribution, rating distributions, and average ratings across watchlists.
- Premium Glassmorphism Design: Responsive visual layout built with modern CSS tokens, custom SVG icons, smooth transition states, skeleton loaders, and a fully polished dark theme.
- Core: React 18, JavaScript (ES6+)
- Build Tool: Vite (for ultra-fast development builds and compilation)
- Styling: Vanilla CSS (CSS Variables, Flexbox, CSS Grid, Glassmorphic effects, responsive layout designs)
- Persistency: HTML5 Local Storage API
- API Framework: FastAPI (Asynchronous Python framework)
- ASGI Server: Uvicorn (local development)
- Serverless Platform: Vercel Serverless Functions (Python runtime)
- HTTP Client: Requests (with
urllib3retry adapters for OMDb metadata aggregation)
Cineverse utilizes a Content-Based Vector Space Model (VSM) to analyze, represent, and recommend movies. To ensure compliance with Vercel's serverless size limits, the execution flow is divided into an Offline Build-Time Precomputation Phase and a Runtime Serverless Inference Phase.
+---------------------------------------------------------------------------------+
| OFFLINE BUILD-TIME PRECOMPUTATION |
| |
| [Raw CSVs] β [Tag Preparation] β [TF-IDF Vectorization] β [Similarity Matrix] |
| β |
| βΌ |
| [movies.json] + [recommendations.json] |
+---------------------------------------------------------------------------------+
β
βΌ
+---------------------------------------------------------------------------------+
| RUNTIME SERVERLESS INFERENCE |
| |
| [Search Query] β [O(1) JSON Lookup] β [Dynamic Sorting/Filtering] β [Response] |
+---------------------------------------------------------------------------------+
Before mathematical modeling, raw metadata from movies.csv and links.csv is parsed and sanitized:
-
Deduplication & Merge: Links and movies are joined via
movieId. We drop rows with missing IMDb identifiers and drop duplicate movies to enforce unique records. -
Title Sanitization: Movie titles are normalized using regular expressions. Parenthetical release years (e.g.,
(1995)) and special characters are stripped out, collapsing all characters to lowercase. - Genre Weight Multiplier: To ensure recommendations are heavily influenced by genre alignment rather than just title terms or release years, the genres text (with pipes replaced by spaces) is duplicated twice in the tags string.
-
Metadata Tag Assembly: For each movie, a raw feature tag string is constructed:
$$\text{Tag String}_d = \text{NormalizedTitle}_d + \text{" "} + \text{Genres}_d + \text{" "} + \text{Genres}_d + \text{" "} + \text{ReleaseYear}_d$$
Example for "Toy Story (1995)":
- Normalized Title:
toy story - Genres:
Adventure Animation Children Comedy Fantasy - Output Tags:
"toy story adventure animation children comedy fantasy adventure animation children comedy fantasy 1995"
The unstructured text tags are converted into numerical feature vectors in a sparse vector space using the Term Frequency-Inverse Document Frequency (TF-IDF) framework.
flowchart TD
A[Processed Tag Strings] --> B[Tokenization & Stop Word Filter]
B --> C[Bi-gram Vocabulary Extraction]
C --> D[Compute Term Frequency TF]
C --> E[Compute Inverse Document Frequency IDF]
D & E --> F[Calculate TF-IDF Weights]
F --> G[L2 Vector Normalization]
G --> H[Sparse CSR Feature Matrix]
- We use a
TfidfVectorizerthat ignores standard English stop words (like "the", "and", "is") which contain no movie search value. -
N-gram Range: Set to
$(1, 2)$ , meaning we extract both unigrams (single words like"story") and bigrams (consecutive word pairs like"toy story"). This captures phrases and compound genres. - The vocabulary represents all unique tokens extracted from the corpus. Let
$V$ be the size of the vocabulary.
For a token
To penalize extremely common words that appear in many documents (e.g., "comedy" or "action") and highlight distinctive keywords, the inverse document frequency is computed as:
- Where
$N$ is the total number of movies in the corpus ($27,278$ ). -
$\text{DF}(t)$ is the document frequency: the number of movies containing token$t$ . - The constants (
$1$ ) prevent division-by-zero errors for out-of-vocabulary terms and ensure non-negative weights.
The raw weight for token
To prevent longer titles or multiple genres from skewing the similarity metrics, we apply
The resulting vector space is stored as a compressed sparse row (CSR) matrix of dimensions
The recommendation engine measures the similarity between two movie vectors
For any target movie, we compute a linear kernel between its vector and the entire matrix to generate a similarity score array of size
To eliminate duplicates during this process:
- Candidates are sorted in descending order of similarity.
- Self-similarity (score of 1.0 against itself) is filtered.
- We track candidate
imdbIdandnormalized_titleto skip duplicates (such as remakes or duplicate listings) and retrieve the top 30 most similar, distinct movies.
To satisfy Vercel's 250 MB size limit for serverless function ZIPs, the dependencies numpy, pandas, scipy, and scikit-learn (which total over 400 MB) are used exclusively locally during the build-time precomputation phase and are omitted entirely from production serverless execution.
- Run precompute.py.
- Load local datasets
movies.csvandlinks.csv. - Run TF-IDF and calculate the pairwise cosine similarity for all movies.
- Write metadata to movies.json.
- Write the similarity relationships map (
movieIdβ list of 30 recommendedmovieIds) to recommendations.json. - Commit the JSON files to Git.
sequenceDiagram
autonumber
Client SPA ->> FastAPI: GET /api/recommend/{query}
FastAPI ->> FastAPI: Normalize and resolve query to movieId
Note over FastAPI: 1. Exact title match<br/>2. Prefix starts-with match<br/>3. Substring contains match
FastAPI ->> recommendations.json: Lookup recommendation IDs (O(1) time)
FastAPI ->> movies.json: Lookup movie details for each ID
FastAPI ->> OMDb Cache: Fetch/Update dynamic posters, plots, and ratings
FastAPI ->> FastAPI: Apply client-requested sorting (alphabet, rating, release year)
FastAPI ->> Client SPA: Return JSON recommendations response
This decoupled architecture achieves sub-millisecond lookups in production, requires less than 20 MB of dependencies, and runs serverlessly on Vercel without package size conflicts.
Cineverse operates as a decoupled single-page application communicating with an asynchronous serverless API:
graph TD
A[React Client SPA] -->|HTTP Request| B[Vercel Serverless Gateway]
B -->|API Routes /api/*| C[FastAPI Serverless Function]
B -->|Static Assets /dist/*| D[Vercel Edge CDN]
C -->|Query| E[(movies.json / recommendations.json)]
C -->|Aggregate missing metadata| F[OMDb Third-party API]
C -->|Read/Write Cache| G[(cache.json)]
- Caching Layer: Standard movie credits and poster URLs are retrieved dynamically from the external OMDb API. These responses are written to a localized caching file cache.json to minimize API latency and request overhead on subsequent visits.
βββ backend/ # Python backend resources
β βββ main.py # Optimized FastAPI routes & JSON query logic
β βββ precompute.py # Local machine TF-IDF & similarity generator
β βββ cache.json # Localized OMDb cache file
β βββ movies.json # [Precomputed] Serialized movie list database
β βββ recommendations.json # [Precomputed] Top-30 recommendation dictionary
β βββ requirements.txt # Lightweight runtime package configurations
βββ frontend-vite/ # React + Vite Single Page Application
β βββ src/
β β βββ components/ # Header, Footer, MovieCard, SkeletonLoader
β β βββ pages/ # Home, MovieDetails, Discover, Watchlist, Analytics
β β βββ App.jsx # App shell and routing configuration
β β βββ main.jsx # Vite React entry point
β βββ package.json # Node dependencies & compilation scripts
β βββ vite.config.js # Vite compiler configurations
βββ api/ # Vercel Serverless Function entry point
β βββ index.py # Handler importing backend FastAPI application
βββ data/ # Raw dataset files (used during precomputation)
β βββ movies.csv # Movie database source (from GroupLens)
β βββ links.csv # Movie-to-IMDb identifier mappings
βββ vercel.json # Vercel edge routes & deployment settings
βββ package.json # Root-level Vercel build trigger script
βββ requirements.txt # Root-level Vercel Python environment packages
βββ README.md # Project documentation
Ensure Python 3.9+ is installed on your system.
# Navigate to the backend directory
cd backend
# Create a virtual environment
python -m venv .venv
# Activate the virtual environment
# On Linux/macOS:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activate
# Install Python requirements
pip install -r requirements.txt
# (Optional) Recompute recommendations if dataset changes:
python precompute.py
# Launch the FastAPI dev server
uvicorn main:app --reload --port 8000The API documentation will be interactive at http://127.0.0.1:8000/docs.
Ensure Node.js is installed.
# Navigate to the frontend directory
cd frontend-vite
# Install npm dependencies
npm install
# Launch Vite development server
npm run devThe client application will run on http://localhost:5173/.
Cineverse is fully configured for Vercel edge deployment:
- Push your updated code to GitHub.
- Link your repository in the Vercel Dashboard.
- Choose the project configuration settings:
- Framework Preset: Select
Other(do NOT selectFastAPIorViteto ensure both Python serverless and React builds are triggered by the root configuration). - Build Command: Stays disabled/default (Vercel automatically triggers the root
package.jsonbuild script). - Output Directory: Stays disabled/default (Vercel automatically redirects to
distas specified invercel.json).
- Framework Preset: Select
- Click Deploy. Vercel will build the frontend assets, set up the static routing, and package the FastAPI serverless function.
For collaborations, feedback, or custom inquiries:
- GitHub: devaprasathk28-dot
- LinkedIn: K Devaprasath
Created by Devaprasath. Β© 2026 Cineverse Recommender.