Lumora
Film & series discovery
- Year
- 2023 — 26
- Formerly the Netflix Clone
- Built with
- Next.js 16, React 19, TypeScript, Tailwind CSS 4 +8 more ↓
- Links
- Live site ↗Source ↗

(01) Overview
Lumora started life as a Netflix clone. I rebuilt it as a product of its own: browse what is trending, open any title to its official trailer, and keep a watchlist that follows you from device to device.
(02) Features
- 01Trailer-first heroA muted trailer fades in over the artwork once it is actually playing, and pauses when it scrolls out of view.
- 02Streamed catalogueRows stream in behind skeletons as their data arrives, with snap scrolling and hover previews.
- 03Title pagesCast, rating, certification and recommendations for every film and series.
- 04My ListSaved to Postgres against your account, with optimistic toggles so the button never waits on the network.
- 05Live searchResults update as you type, and the query lives in the URL so a search can be shared.
- 06Guest modeOne click into a shared demo account, alongside email and password sign-up.
(03) Screens




(04) On a phone
Same app, smaller screen.
Captured from the live site at 390 pixels wide — the width of most phones in a hand.


(05) Stack
Twelve tools, and the job each one does here.
- FrameworkNext.js16App Router, Server Components and Server Actions
- UIReact19useOptimistic keeps My List instant
- LanguageTypeScriptTyped from the database schema to generated route types
- StylingTailwind CSS4The whole interface, from tokens up
- DataPostgreSQLAccounts and watchlists, with row-level security on
- DataDrizzle ORMSchema, SQL migrations and Drizzle Studio
- DataZodValidates the input of every Server Action
- AuthNextAuthEmail and password, plus a one-click guest account
- ServicesTMDB APICatalogue, cast, ratings and recommendations
- ServicesYouTubeOfficial trailers, through the no-cookie player
- UILucideIcons
- HostingVercelProduction hosting
(06) Under the hood
- 01
Catalogue data is fetched in Server Components and cached for an hour. The TMDB client is marked server-only, so the API token can never be bundled for the browser.
- 02
Every write is a Server Action with its input parsed by Zod. Passwords are hashed with bcrypt and never stored or logged in plain text.
- 03
Migrations switch on row-level security for every table, so a hosted Postgres such as Supabase cannot leak users through its public API.
- 04
The hero trailer is skipped on small screens, with data saver on and for reduced motion. Focus states are visible throughout, and phones get a tab bar within reach of a thumb.
Next case
CryptoTracker