A cross-platform mobile app for tracking, reviewing, and discovering video games — with a one-tap Steam library import, a community review system, and a gamified XP/level progression. Built with Expo (React Native) and a self-hosted Node.js + PostgreSQL backend.
Think Letterboxd, but for games — and it imports your entire Steam library automatically.
- 🔗 Steam library import — Connect your Steam account (OpenID 2.0, in-app WebView) and auto-import your whole owned library with playtime, matched against the IGDB game database (~90%+ match rate on real libraries). Non-games (demos, tools, soundtracks) are filtered out; unmatched titles are surfaced for review.
- 📝 Reviews & community — Write reviews (rating, playtime, difficulty, platform, tags, status). See other players' reviews on each game, sort by newest/top-rated, mark reviews helpful, and tap through to a reviewer's public profile.
- 📚 Library & custom lists — Track games in a personal library and organize them into custom lists, all persisted server-side.
- 🏆 XP & levels — An earned, append-only XP system (reviews, library adds, lists, achievements, and Steam playtime) drives a level + rank progression that survives reinstalls and can never be lost by deleting content.
- 📊 Activity feed & streaks — A real per-user activity timeline and a day-streak computed from genuine activity dates.
- 🔍 Discovery — Browse Featured, Popular, Hidden Gems, and genre categories powered by live IGDB data, with full search and paginated category screens.
- 📺 In-app media — Watch game trailers (YouTube) and live Twitch streams inside the app with a YouTube-style fullscreen player.
- 🎨 Polished UI — A custom teal design system, themed modals, achievement-unlock animations, and smooth navigation transitions.
Mobile (Expo / React Native)
- Expo SDK 54, expo-router (file-based routing), React Native 0.81
- Zustand for state, TanStack Query for server state
- NativeWind (Tailwind) for styling
react-native-webview,react-native-youtube-iframe,expo-screen-orientation(in-app players + real fullscreen)
Backend (Node.js)
- Express REST API, PostgreSQL (
pg) - JWT auth (bcrypt password hashing),
helmet+ rate-limiting - IGDB (via Twitch OAuth) game data proxy · Twitch Helix live streams · Steam Web API + OpenID · Cloudinary media storage
┌─────────────────────────┐ ┌──────────────────────────────┐
│ Expo / React Native │ HTTPS │ Node.js + Express API │
│ (iOS · Android · Web) │ ──────► │ │
│ │ │ auth · reviews · library │
│ Zustand · React Query │ │ lists · xp · activity │
│ NativeWind │ ◄────── │ steam · games · twitch │
└─────────────────────────┘ JSON └───────────────┬──────────────┘
│
┌──────────────────────────┼───────────────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────────┐ ┌──────────────────┐
│ PostgreSQL│ │ External APIs │ │ Cloudinary │
│ (9 tables)│ │ IGDB · Twitch │ │ (avatars/media) │
│ │ │ Steam │ │ │
└───────────┘ └───────────────┘ └──────────────────┘
The client never talks to IGDB/Twitch/Steam directly — the backend proxies them so API secrets stay server-side and OpenID verification happens where it's trusted.
Database tables: users, reviews, review_votes, library_games, game_lists, game_list_items, xp_events, activity_events, steam_unmatched_games.
- Node.js 20+
- PostgreSQL 14+
- Free API credentials: IGDB/Twitch, Steam, Cloudinary
cd backend
cp .env.example .env # fill in DATABASE_URL + API keys
npm install
npm run db:init # create tables (idempotent)
npm run dev # http://localhost:3001# from the repo root
cp .env.example .env # set EXPO_PUBLIC_API_URL to your backend URL
npm install
npm run dev # Expo dev server (use a dev client, not Expo Go)Steam import on a device: set
PUBLIC_BASE_URLinbackend/.envto a URL your phone can reach (your LAN IP in dev, e.g.http://192.168.1.5:3001, or the deployed URL). Steam redirects the in-app WebView back to it —localhostwon't work from a physical device.
The backend ships with a Render Blueprint (backend/render.yaml) that provisions the web service and a managed Postgres together. See DEPLOYMENT.md for the full walkthrough. The schema is applied automatically on deploy (db:init is idempotent), and SSL is auto-enabled for hosted databases.
- Passwords hashed with bcrypt; stateless JWTs.
- API secrets (IGDB/Steam/Cloudinary) live only on the server; the client uses proxy endpoints.
- Steam OpenID responses are verified server-to-server before a SteamID is trusted.
helmetsecurity headers + auth rate-limiting; per-user data scoped by JWT.
Built by Sourabh Saini.