Building a Movie Discovery App with TMDB API and Next.js
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.