How I Built a Semantic Recommendation Engine for 80,000 Steam Games
NextSteamGame is a Steam recommendation project built around a simple complaint: most game recommenders know that two games are related, but they rarely explain why. Player-overlap signals are useful, but they flatten intent. Someone may like Persona 5 for the jazz fusion soundtrack and modern Tokyo setting; another person may like it for social simulation and dungeon crawling. Those are different reasons, and a good recommendation system should let users separate them.
I think games can be represented as weighted profiles: not just genre, but the parts that actually make the game feel like itself.
Persona 5 Royal: jazz fusion, modern urban fantasy, social simulation, dungeon crawling, stylish UI.
The problem
Most recommendation systems lean on the pattern "players who liked X also liked Y." That works well for popular games, but it struggles with niche tastes and gives weak explanations. I wanted a system that could represent a game as a shape: soundtrack, setting, systems, narrative, vibe, and the small micro-tags that genre labels leave behind.
The pipeline
- Collect Steam metadata, appids, genres, tags, descriptions, release data, and storefront artwork.
- Pull up to 2,000 reviews per game, then remove spam and low-signal reviews with regex filters, word diversity scoring, quality heuristics, and descriptive phrase detection.
- Classify useful reviews with ModernBERT into pools for gameplay, art, soundtrack, systems depth, narrative, and general description.
- Generate semantic identity data: focus vectors, mechanics, narrative, vibe, structure loop, signature tags, niche anchors, music tags, and micro-tags.
- Canonicalize noisy generated tags with heuristics, fuzzy matching, embedding similarity, and vector search so tags like fast action, quick action, and high-speed combat can be grouped without losing useful distinctions.
- Precompute candidate relationships offline, then let the live FastAPI and React app apply user-controlled reranking at runtime.
Why the architecture is cool
The key design choice is splitting expensive semantic work from cheap interactive reranking. Computing every similarity at runtime would be wasteful, so candidate relationships are built offline. When a user searches, the app retrieves candidates, applies the user's weights, and reranks recommendations based on the profile dimensions they care about.
From review to recommendation
A raw review like "the combat is fast, the soundtrack goes hard, and the boss fights feel like rhythm puzzles" becomes structured signals: fast combat, high-energy soundtrack, boss-focused structure, rhythm-like timing, and mechanical precision. Those signals can then be weighted independently by the user.
What it demonstrates
- 80,000+ Steam games indexed
- Up to 2,000 reviews analyzed per game
- Semantic vectors, identity tags, and canonicalized genre/tag relationships
- 30,000+ users and discovery across 8,000+ unique games
- A retrieval design cheap enough to run on constrained cloud infrastructure
What I learned
Review text is noisy, so filtering before embeddings matters. LLM-generated tags are useful, but raw generated tags need canonicalization. Most importantly, recommendations feel better when users can inspect and control the reason behind a match instead of accepting a mystery list.
Future Tilt
Superlinked (Series A)
USF MAGIC Lab
Candle Stories
iD Tech Camps (Stanford)
UC Merced to SATAL
Acme Builders Incorporated






