A swipe-first movie decision app that helps people quickly and fairly choose what to watch.
Every movie shown can actually be watched in the country you live in. No US-only Netflix results shown to EU users. No guessing. No disappointment.
- Zero UI at top: Nothing may appear at the top of screen. Only OS status bar exists.
- Film dominates: The poster IS the interface. ~80% of screen is the movie poster.
- Bottom-driven interaction: All controls at bottom, thumb-reachable.
- Spotify-level calm: Few choices, no explanation needed, content first.
- No AI smell: Real TMDB posters, quality-gated content, no generated art.
- Poster-first: Beautiful movie posters are the primary experience. Trailers disabled until rebuilt.
- Completely empty (only OS status bar)
- No icons, buttons, navigation, or labels
- This area is silent
- Full-bleed official movie poster
- Title + year only, subtle at bottom
- No metadata, ratings, or debug overlays
- Gesture-responsive (swipe left/right/up)
- Poster-only: Trailers disabled until system is rebuilt
- Single horizontal row
- Rectangular brand buttons with rounded corners
- Proper brand colors and wordmarks matching reference (public/image-1.png)
- Netflix (black bg, red text), Prime Video (dark bg, white text + blue swoosh), Disney+ (navy gradient), HBO Max (purple gradient), Hulu (green bg), Apple TV+ (black bg), etc.
- Non-interactive: Icons are passive availability signals only
- Max 4 icons shown
- Supported: netflix, prime, disney, hbo, apple, hulu, paramount, peacock, viaplay, svtplay, mubi, crunchyroll, youtubetv
Three actions (left to right):
- Pass (red X)
- Save (yellow bookmark)
- Like (green heart) Icons only. Haptic feedback on press.
Below action bar, always visible:
- Spelläge (game mode)
- Settings
- All movies use official TMDB poster paths
- No stock images, no placeholders, no AI-generated art
- Movies must pass quality gate: rating_count >= 1000 AND rating_avg >= 6.5
- Hidden gems exception: rating_avg >= 8.0 with 500+ votes
- If poster fails to load, movie is removed from feed
- Feed NEVER ends - fallback ladder ensures continuous content
- Personalized recommendations based on your taste profile
- Quality-filtered buckets: trending, top-rated, popular, new releases, hidden gems
- Never runs out - multiple fallback levels ensure continuous content
- Learns from likes, passes, and saves in real-time
- Diversity constraints prevent genre/director streaks
- Swipe right to like, left to pass, up to save for later
- Physics-based gestures with haptic feedback
- Bottom action buttons as alternative to swipes
- Title + year only on cards
- Country-accurate streaming availability
Trailers are completely disabled until the system is rebuilt with proper architecture.
Why disabled:
- YouTube embeds don't allow reliable muted autoplay
- iOS blocks playback in many scenarios
- WebViews unload on re-render causing instant stops
- Error 153 = player config + policy mismatch
Current state: Posters only. No autoplay. No long-press. No inline video.
Future rebuild will use:
- ONE persistent video player per feed (not per card)
- Source-agnostic: MP4, HLS, CDN clips, Apple previews, Vimeo
- Player lives ABOVE card stack, only source swaps
- Validation gate: 50 consecutive autoplay successes required
- Sprite sheet icons only: All icons from public/image-2.png (9x3 grid)
- Raw brand images: No containers, pills, backgrounds, or overlays
- Non-interactive: Icons are passive availability signals, not buttons
- Brand fidelity: Original colors, shapes, aspect ratios preserved
- Available providers: Netflix, Prime Video, HBO Max, Hulu, Disney+, Apple TV+, CBS, AMC, Showtime, MUBI, Crunchyroll, Rakuten TV, Acorn TV, Plex, and more
- Regional accuracy: Only show icons if movie is confirmed available in user's region
- Official TMDB movie posters (w500 = 500px wide)
- Image prefetching for smooth scrolling
- Memory + disk caching via expo-image
- Placeholder blur hash during loading
- Pure black background (#000000)
The ONLY premium feature in Glo. Contains two modes:
- Pick a mood: Calm, Fun, Intense, Short, or Surprise Me
- Blind choice: Movie titles hidden until you like/save
- Filtered movie selection based on mood
- After 5 likes, a random winner is dramatically revealed
- Winner auto-plays trailer inline
- Same as Solo, but with a shareable room code
- Join with a 6-character code
- Both participants swipe blind (titles hidden)
- Match confirmation when both like the same movie
- Winner revealed with cinematic trailer
- Saved Movies: Grid view of all saved movies
- Liked Movies: Grid view of all liked movies
- Tap to view details with streaming providers
- Quick save/remove actions
- Same posters as main feed
- Expo SDK 53 with React Native 0.76.7
- NativeWind + Tailwind CSS for styling
- React Native Reanimated for animations
- React Native Gesture Handler for swipes
- Zustand for state management with persistence
- expo-image for optimized image loading
- react-native-webview for inline trailer playback (YouTube IFrame API)
src/
├── app/
│ ├── _layout.tsx # Root layout with navigation
│ ├── index.tsx # Home screen (Quick Swipe)
│ ├── settings.tsx # Settings modal with My Library
│ ├── saved.tsx # Saved movies grid
│ ├── liked.tsx # Liked movies grid
│ ├── spellage.tsx # Spelläge mode picker (Solo/Together)
│ └── session.tsx # Active game session with blind choice
├── components/
│ ├── MovieCard.tsx # Main card with swipe + hold-to-preview + blind mode
│ ├── StreamingIcon.tsx # Sprite sheet icons + deep links
│ └── YouTubePlayer.tsx # IFrame Player API component
└── lib/
├── types.ts # TypeScript interfaces
├── constants.ts # App constants and config
├── store.ts # Zustand store with taste profile
├── movies.ts # Movie data with availability
├── feed-engine.ts # Recommendation algorithm
├── candidate-store.ts # Quality-filtered buckets
├── trailer.ts # YouTube trailer system + cache
├── streaming.ts # Provider deep linking
├── image-cache.ts # Image prefetch utilities
├── tmdb.ts # TMDB API types and helpers
└── cn.ts # ClassName utility
Trailers are currently disabled. This section documents the planned architecture for when they are re-enabled.
- ONE persistent video player per feed
- Never mount/unmount per card
- Only swap video source
- Player lives ABOVE card stack
- Cards do not own players
- Source-agnostic: MP4, HLS, CDN clips, Apple previews, Vimeo, etc.
- 50 consecutive autoplay attempts succeed
- 0 instant stops
- 0 silent failures
- 0 blocking swipes
- 0 UI regressions
Trailers are ONLY enabled when both gates pass:
Gate A — Icon Correctness
- Raw brand logos
- No wrappers/pills/backgrounds
- Non-interactive
- Matches reference exactly
Gate B — Trailer Stability
- Autoplay works reliably
- No blink-start-stop
- No silent failures
- Playback always stops instantly on swipe
If either gate fails → trailers disabled, poster-only experience
- Uses official YouTube IFrame Player API for reliable playback
- Fixes Error 153 that occurs with direct embedding
- WebView configured with:
allowsInlineMediaPlayback={true}mediaPlaybackRequiresUserAction={false}- Proper origin and playsinline parameters
- Official/Studio (top priority):
"{title} {year} official trailer" - Distributor/Platform:
"{title} trailer {year}" - Trusted channels (last resort): Known trailer aggregators
- Duration: 45-240 seconds
- Must contain "trailer" or "teaser" in title
- Blacklist: reactions, breakdowns, fan edits, scene clips
- Verified channels: Warner Bros, Universal, Sony, Disney, etc.
- Key:
trailer_{movieId}_{region}_{language} - TTL: 7 days
- Fallback: Poster-only experience is acceptable
The FeedEngine uses a multi-bucket candidate store with quality filters:
- Trending: High popularity, recent attention
- Top Rated: Rating ≥7.0, ≥1000 votes
- Popular: High popularity score + decent ratings
- New & Noteworthy: Released within 365 days, good ratings
- Hidden Gems: Rating ≥7.5, <5000 votes
- Personalized: Scored by taste profile
- 50% Personalized picks
- 15% Trending
- 15% Top Rated
- 10% Popular
- 5% New Releases
- 5% Hidden Gems
- Genres: Weighted affinities (like +0.15, save +0.25, pass -0.08)
- Directors/Cast: Strong signals from likes/saves
- Moods: Calm, fun, intense preferences
- Runtime: Running average of liked movies
- Era: Classic, modern, recent preferences
- Trailers: Engagement refines taste (minor weight)
- Max 3 same-genre in a row
- Max 2 same-director in a row
- Max 4 same-era in a row
- Fresh candidates (not seen, not in history)
- All unswiped movies (ignore history window)
- Previously swiped (except saved)
- Any movie in region (ultimate fallback)
Sweden, USA, UK, Germany, France, Norway, Denmark, Finland, Netherlands, Australia, Canada
One-time App Store purchase. Everything unlocked.
- No subscriptions
- No ads
- No tracking