Cinemap · 2024–2026 Product design · ML systems

A movie app that maps how films feel

Cinemap is a discovery engine over 140,000+ films and shows that turns every title into a point in a learned 85-dimensional space — fusing 35 LLM-scored emotional dimensions with a social graph of who-makes-what into a GNN. One embedding space; a web feed and a five-tab mobile app built on top of it.

Role  Design · Engineering · ML pipeline / Platforms  iOS (React Native) · Web (Next.js) / Stack  Supabase · pgvector · Python
trycinemap.com/foryou
Cinemap web feed — a personalized, login-free For You feed
Cinemap mobile Discover tab
The problem

Most recommenders treat a film as a bag of categorical tags. So they hand you more of the same.

Genre says Inception is "sci-fi / action." Even micro-genres like "mind-bender" are still insufficient. The key is marrying micro-genres with emotional feel to capture genuine neighbours.

Two films can share zero genres yet feel like siblings. No metadata field encodes that. Cinemap's bet was to learn it instead.

The thesis

Every title becomes a point in a learned space.

Concatenate two orthogonal axes of what a film is into a single 85-dimensional embedding. Once a film is a point, every product surface becomes geometry: browse is sampling, similarity is nearest-neighbors, personalization is navigating toward your taste.

Axis 01 · affective

How a film feels

An LLM scores every title across 35 continuous emotional dimensions — humour, darkness, tension, awe, existential weight — giving a dense, polarity-rich fingerprint that genres can't express.

35-d · ~95% of the geometry
Axis 02 · collaborative

Who makes it

Films and the people who make them form a weighted bipartite graph. A spectral embedding over it captures the latent collaborative manifold — the who-works-with-whom signal no field encodes.

50-d · graph spectral block
embedding(title) = [ 35-d affective ]    [ 50-d graph spectral ]    vector(85)  // indexed in pgvector HNSW · NN over 140k titles in ms
Surface 01 · web

A login-free feed that learns you in a single session.

The web "For You" feed personalizes client-side from implicit signals — how long you dwell on a trailer, what you skip — with no account. A calibration bar shows the model warming up in real time.

Cinemap web feed showing Inception with a personalization progress bar and emotional radar
Cinemap web detail panel — ratings, streaming, and a More Like This rail powered by nearest-neighbor search
Detail · more like this

Open any title and the “More Like This” rail is pure geometric retrieval — approximate nearest neighbors in the 85-d space, oversampled and diversity-capped so a single prolific director can't dominate the results.

dwell ≥ 3s → seed dwell ≤ 1.5s → skip centroid → get_anon_recommendations
Surface 02 · iOS

Five tabs, one embedding space.

The mobile app is React Native / Expo. Every discovery surface reads the same query vector — media type, mood sliders, themes, streaming services — and hits a different strategy against the same learned manifold.

Discover tab
Discover

Trailer-first For You

A full-bleed, auto-playing feed with the title's emotional radar overlaid and live mood chips.

Map the mood filter
Filter · vibe

Map the mood

Drag dots on the radar to filter by feeling — the affective axis turned into a direct-manipulation control.

Themes filter
Filter · themes

Microgenres

Curated tags — Cyberpunk, Home Invasion, '70s Paranoia — combined as OR sets and used as a diversity constraint.

Guided onboarding
Guided

Seed → similar

A wizard that turns "what do you wish you could watch for the first time?" into seed nodes for the engine.

Boards list
Boards

Editor & public lists

Curated and user lists — editorial collections sit beside anything the community makes public.

Board detail
Boards · detail

Make it personal

A masonry of posters with a human voice — “movies my friend Mike will enjoy over 4–5 Miller Lites.”

Movie detail with emotional profile
Title detail

Emotional profile

Ratings, streaming, trailer and the signature radar — the affective fingerprint made legible.

Streaming filter
Filter · streaming

Where you actually have it

Per-country availability with array-overlap filtering, so results respect the services you pay for.

← scroll · drag to explore the surfaces →

The signature motif

The emotional fingerprint.

Nine of the 35 affective dimensions, drawn as a radar, became Cinemap's defining visual. It's a read-out on every title — and, with draggable dots, a control that filters the catalog by feeling.

Now showing: Inception

Romantic Funny Dark Epic Unpredictable Fantastical Tense Violent Scary
Under the hood

From catalog to geometry.

A Python representation-learning pipeline ingests the catalog and learns the node embeddings — then every product surface just queries the same space.

01 · ingest
TMDB + OMDB
Titles, full credits, trailers, ratings, availability — plus public reviews & articles.
02 · score
LLM affect
Claude scores 35 emotional dims with anchored examples and deliberate polarity for sharp geometry.
03 · graph
Spectral SVD
Truncated SVD over the role-weighted movie–person adjacency → 50 spectral components.
04 · learn
Auteur GNN
A graph neural net refines the initial scores via auteur similarity — learned message passing over the creator graph.
05 · serve
pgvector HNSW
85-d vectors upserted and indexed; browse, similarity & personalization all read it.
Strategy A

Stratified manifold sampling

Browse without a full-table scan: partition the id-space into strata, probe a few per stratum, and rotate 3 random affective dims per call so every batch is vibe-coherent but fresh.

Strategy B

Approximate nearest neighbors

Similarity, guided and co-watch are ANN in 85-d. Filtered ANN uses a CTE-join pattern to dodge HNSW's pre-filter hijack, with a per-director diversity cap.

Strategy C

Taste-centroid personalization

A user is a small set of k-means centroids in the same space as the films. ~75% exploitation by proximity, ~25% serendipity capped to one per microgenre.

140k+
Titles in the graph
85
Embedding dimensions
35
Affective dimensions
~20ms
Person traversal (was ~5s)
Thanks for scrolling

Designed, built & trained.

Cinemap is a solo passion project that I've been working on since 2020. Always looking for feedback, ideas, or to just talk about movies.