Replace search page with explore page for rich discovery experience

The command palette (⌘K) already handles direct title search. Replace the
redundant /search page with a new /explore page featuring trending titles,
popular movies/TV, and genre browsing powered by TMDB discovery endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 15:11:53 -05:00
co-authored by Claude Opus 4.6
parent cddef34909
commit e098180dda
14 changed files with 653 additions and 120 deletions
+41
View File
@@ -1,4 +1,5 @@
import type {
TmdbGenreListResponse,
TmdbMovieDetails,
TmdbRecommendationResponse,
TmdbSearchResponse,
@@ -18,6 +19,7 @@ function getApiKey() {
async function tmdbFetch<T>(
path: string,
params?: Record<string, string>,
fetchOptions?: RequestInit,
): Promise<T> {
const url = new URL(`${BASE_URL}${path}`);
if (params) {
@@ -27,9 +29,11 @@ async function tmdbFetch<T>(
}
const res = await fetch(url.toString(), {
...fetchOptions,
headers: {
Authorization: `Bearer ${getApiKey()}`,
Accept: "application/json",
...fetchOptions?.headers,
},
});
@@ -90,4 +94,41 @@ export async function getSimilar(tmdbId: number, type: "movie" | "tv") {
return tmdbFetch<TmdbRecommendationResponse>(`/${type}/${tmdbId}/similar`);
}
export async function getTrending(
mediaType: "all" | "movie" | "tv",
timeWindow: "day" | "week" = "day",
) {
return tmdbFetch<TmdbSearchResponse>(
`/trending/${mediaType}/${timeWindow}`,
undefined,
{ next: { revalidate: 3600 } },
);
}
export async function getPopular(type: "movie" | "tv", page = 1) {
return tmdbFetch<TmdbSearchResponse>(
`/${type}/popular`,
{ page: String(page) },
{ next: { revalidate: 3600 } },
);
}
export async function getGenres(type: "movie" | "tv") {
return tmdbFetch<TmdbGenreListResponse>(`/genre/${type}/list`, undefined, {
next: { revalidate: 86400 },
});
}
export async function discover(
type: "movie" | "tv",
params: Record<string, string>,
page = 1,
) {
return tmdbFetch<TmdbSearchResponse>(
`/discover/${type}`,
{ ...params, page: String(page) },
{ next: { revalidate: 3600 } },
);
}
export { tmdbImageUrl } from "./image";
+9
View File
@@ -110,3 +110,12 @@ export interface TmdbRecommendationResponse {
total_pages: number;
total_results: number;
}
export interface TmdbGenre {
id: number;
name: string;
}
export interface TmdbGenreListResponse {
genres: TmdbGenre[];
}