The Problem
Finding something to watch shouldn't feel like a chore. Legacy movie sites are often weighed down by heavy ads, sluggish page transitions, and buried streaming links. I wanted a tool that got straight to the point: instant search, immediate streaming availability, and quick, objective AI synopses.
So, I solo-developed Galaxy Movies.
Live Demo: https://www.galaxymovies.app/
GitHub: https://github.com/NickFasulo/galaxy-movies
Key Features
Lightning-Fast Search: Browse thousands of titles and explore cast networks in a clean, cosmic dark-mode UI.
One-Click Streaming Check: Instantly view exact platform availability (where to stream, rent, or buy) without jumping through menus.
Instant AI Synopses: Concise, objective film overviews powered by OpenAI to give quick context before pressing play.
Dynamic OG Cards: Social share preview cards rendered on the fly with custom branding.
Tech Stack & Architecture Highlights
- Frontend: Next.js (Pages Router) + Chakra UI
- State & Data: React Query + TMDB API
-
Edge & AI Services: Vercel Edge Runtime (
@vercel/og) + OpenAI API - Quality Assurance: Lighthouse CI
-
Dynamic Social Cards on Vercel Edge Runtime: Built dynamic Open Graph image generation using
@vercel/og. Requests parse title and poster data on Edge functions to serve custom social cards with sub-100ms response times. - TMDB Image Optimization Bypass: Direct-to-CDN poster loading to bypass server image transformation limits while maintaining high performance.
- Automated Quality Checks: Integrated Lighthouse CI to enforce performance, accessibility, and SEO thresholds on builds.
Top comments (3)
The dynamic OG cards are a nice touch. Two things I'd check since both the cards and the synopses sit on paid or rate-limited calls:
@vercel/ogresponse has a longCache-Control(e.g.public, s-maxage=86400, stale-while-revalidate=604800). Link unfurlers from Slack, Discord, X and iMessage each fetch the image, sometimes several times per paste. Without CDN caching every share re-renders the card and re-hits TMDB.Did Lighthouse CI flag anything on the poster-heavy pages, like LCP from the first poster image?
Great catches! Since then I've implemented these changes.
The OG route ships with s-maxage=604800, stale-while-revalidate=2592000 plus Vercel-CDN-Cache-Control, so unfurler re-fetches should never reach the function. There's a per-IP rate limit as a backstop, and ?poster= is locked to a TMDB-only pattern so it can't be used as an open image proxy. Fun bug I hit: TMDB serves webp on .jpg paths, which crashes Satori. Now the fetch checks content-type and falls back to a text-only card.
The synopsis is generated once per TMDB id into Redis with a 1-year TTL under a versioned key, with an in-memory LRU in front. Generation is capped globally and wrapped in a timeout during SSR. A miss just renders the page without that section. Crawlers never trigger generation, and their AI-less renders go out no-store so they can't poison the shared cache.
LCP was exactly what Lighthouse flagged. That's why the first row of posters and the detail backdrop get fetchPriority="high". CLS ended up as the hard gate since fixed-size poster frames make it easy
Thanks for checking out Galaxy Movies! š
Drop a comment if you test it out on mobile or desktop. Iām hanging out in the comments to answer any technical questions about the architecture or feature requests!