A modern, full-stack movie discovery application built with cutting-edge React technologies. Browse popular movies, explore TV shows, watch trailers, and save your favorites - all powered by the TMDB API.
- Movie Discovery - Browse movies by category (Popular, Top Rated, Upcoming, Now Playing)
- Genre Filtering - Filter movies by genre with smooth navigation
- TV Shows - Explore trending and popular TV series
- Movie Details - View comprehensive movie information including:
- Cast & crew details
- Production companies
- Trailers (YouTube embedded)
- Image galleries with carousel
- Recommendations
- Cast Profiles - Explore filmographies and biographical information
- Search - Quick search with command palette (Cmd/Ctrl + K)
- User Lists - Save favorites and watch later lists (requires authentication)
- Authentication - Secure sign-in with Clerk
- Infinite Scrolling - Seamless content loading with virtualized lists
- Responsive Design - Optimized for all screen sizes
- Dark Mode - Beautiful dark theme with gradient overlays
| Technology | Description |
|---|---|
| TanStack Start | Full-stack React framework with SSR |
| TanStack Router | Type-safe file-based routing with Zod validation |
| TanStack Query | Server state management with SSR integration |
| TanStack Virtual | Virtualized lists for performance |
| React 19 | Latest React with React Compiler |
| Tailwind CSS v4 | Utility-first CSS framework |
| Radix UI | Unstyled, accessible UI primitives |
| Lucide Icons | Beautiful SVG icons |
| Technology | Description |
|---|---|
| Convex | Real-time backend-as-a-service |
| Clerk | Authentication and user management |
| TMDB API | Movie and TV show data |
| Technology | Description |
|---|---|
| Vite | Next-generation frontend tooling |
| TypeScript | Type-safe JavaScript |
| Biome | Fast formatter and linter |
| Cloudflare Workers | Edge deployment |
- Node.js 20+
- pnpm (recommended) or npm
- TMDB API key
- Convex account
- Clerk account
Create a .env file in the root directory:
# TMDB API
TMDB_API_KEY=your_tmdb_api_key
# Convex
VITE_CONVEX_URL=your_convex_deployment_url
# Clerk
VITE_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key# Clone the repository
git clone https://github.com/enyelsequeira/tanstack-start-movies.git
cd tanstack-start-movies
# Install dependencies
pnpm install
# Start the Convex development server (in a separate terminal)
npx convex dev
# Start the development server
pnpm devThe application will be available at http://localhost:3000.
| Command | Description |
|---|---|
pnpm dev |
Start development server on port 3000 |
pnpm build |
Build for production |
pnpm serve |
Preview production build |
pnpm test |
Run tests with Vitest |
pnpm lint |
Lint with Biome |
pnpm format |
Format with Biome |
pnpm check |
Run Biome check (lint + format) |
pnpm deploy |
Deploy to Cloudflare Workers |
tanstack-start-movies/
├── convex/ # Convex backend
│ ├── schema.ts # Database schema
│ ├── favorites.ts # Favorites mutations/queries
│ └── watchLater.ts # Watch later mutations/queries
├── src/
│ ├── components/ # React components
│ │ ├── ui/ # Reusable UI components (shadcn/ui style)
│ │ ├── movie-hero.tsx # Hero section component
│ │ ├── movie-card.tsx # Movie card component
│ │ └── ...
│ ├── routes/ # File-based routes
│ │ ├── __root.tsx # Root layout
│ │ ├── index.tsx # Home page
│ │ ├── movies/
│ │ │ └── $movie.tsx # Movie detail page
│ │ ├── shows/
│ │ │ └── $show.tsx # TV show detail page
│ │ ├── cast/
│ │ │ └── $cast.tsx # Cast profile page
│ │ └── profile/
│ │ └── $profile.tsx # User profile page
│ ├── queries/ # TanStack Query functions
│ ├── lib/ # Utilities and types
│ └── integrations/ # Provider wrappers
├── public/ # Static assets
└── package.json
export const Route = createFileRoute("/movies/$movie")({
component: RouteComponent,
validateSearch: zodSchema,
loader: async ({ context, params }) => {
// SSR data fetching
return context.queryClient.ensureQueryData(
fetchMovieInfoOptions({ movieId: params.movie })
);
},
});// Queries export three items: fetch function, queryOptions, and hook
export const fetchMovieInfo = async (movieId: string) => { /* ... */ };
export const fetchMovieInfoOptions = (params) => queryOptions({
queryKey: ["movie", params.movieId],
queryFn: () => fetchMovieInfo(params.movieId),
});
export const useMovieInfo = (params) => useQuery(fetchMovieInfoOptions(params));The application uses Convex for real-time data with the following tables:
- users - User profiles synced from Clerk
- favorites - User's favorite movies and shows
- watchLater - User's watch later list
- sessions - User session tracking
# Build and deploy
pnpm build
pnpm deployConfigure your wrangler.jsonc for environment variables and deployment settings.
This product uses the TMDB API but is not endorsed or certified by TMDB.
MIT License - feel free to use this project for learning or as a starting point for your own applications.
Built by ESCodes
Star this repo if you found it useful!