Tutorial5 min readMarch 2025

Building a Movie Discovery App with TMDB API and Next.js

O

Olamilekan Kilani

Frontend Developer

Overview

I built a movie discovery web application using the TMDB (The Movie Database) API that allows users to explore trending movies and TV shows in a clean, responsive interface. The goal was to build something visually engaging — inspired by modern streaming platforms like Netflix — while learning how to work with a real third-party API.

You can check it out live at tdmb-tau.vercel.app.

Tech Stack

  • Frontend: Next.js, React, TypeScript
  • State Management: Redux Toolkit
  • Styling: CSS Modules / Styled Components
  • API: TMDB REST API
  • Deployment: Vercel

Key Features

Real-Time Search

Users can search for any movie or TV show and get instant results. I implemented debouncing to avoid firing API calls on every keystroke — only searching after the user stops typing for 500ms.

Dynamic Filtering

Users can switch between Movies and TV Shows with a single click. The filter updates the API endpoint and re-renders the results without a full page reload.

Horizontal Scrolling Layout

One of the most satisfying UI features was the horizontal scrolling card layout — similar to what you see on Netflix. Each row represents a category (Trending, Popular, Latest) and scrolls independently.

// Example of horizontal scroll container
<div className="flex gap-4 overflow-x-auto scrollbar-hide pb-4">
  {movies.map((movie) => (
    <MovieCard key={movie.id} movie={movie} />
  ))}
</div>

Latest Trailers

Each movie has a trailer section that fetches the official YouTube trailer from TMDB and plays it directly in the app — no redirecting to YouTube.

Dynamic Routing

Clicking on any movie takes you to a dedicated detail page at /movies/[id] with full info — cast, overview, ratings, runtime and related movies.

State Management with Redux Toolkit

Managing search results and movie data across multiple components needed a proper solution. I used Redux Toolkit because:

  • createSlice makes reducers clean and readable
  • createAsyncThunk handles async API calls with loading/error states
  • The Redux DevTools extension made debugging easy
const moviesSlice = createSlice({
  name: 'movies',
  initialState: { data: [], loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchMovies.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchMovies.fulfilled, (state, action) => {
        state.loading = false;
        state.data = action.payload;
      });
  },
});

Challenges I Faced

TMDB API Rate Limits

TMDB has rate limits so I had to implement proper error handling and avoid unnecessary API calls. Caching results with Redux helped reduce repeated requests.

Image Optimization

TMDB returns image paths like /abc123.jpg — not full URLs. I had to prepend the base URL:

const IMAGE_BASE = 'https://image.tmdb.org/t/p/w500';
const imageUrl = `${IMAGE_BASE}${movie.poster_path}`;

Responsive Design

Making the horizontal scroll work properly on both mobile and desktop took some work. The key was using overflow-x-auto with scrollbar-hide and fixed card widths.

What I Learned

  • How to work with a real third-party REST API
  • Redux Toolkit for scalable state management
  • Dynamic routing in Next.js App Router
  • Building Netflix-inspired UI layouts
  • Optimizing data fetching for fast load times

Conclusion

This project was my first big project, so i was getting instructions on what part to build and what not, a great way to practice working with external APIs and state management at scale. The TMDB API is well documented and perfect for building portfolio projects. Check out the live app at tdmb-tau.vercel.app and the code on my GitHub.