CineStack is a full-stack movie platform built as a portfolio project to demonstrate modern web development engineering. It integrates with The Movie Database (TMDB) API to provide a rich catalog of films, complete with user reviews, ratings, watchlists, and an admin panel.
This project showcases production-grade full-stack development skills:
Clean Architecture — Separation of concerns between server components, client components, API routes, and database layer.
Type Safety — Full TypeScript strict mode with zero any types.
Real-World Features — Authentication, rate limiting, admin panel, CRUD operations, relational data modeling, and external API integration.
Performance — ISR caching, optimized images, efficient database queries, and lazy loading.
UI/UX — Cinematic dark theme, responsive design, micro-interactions, and accessibility.
Recruiters & Clients — See production-quality code with real-world architecture decisions.
Developers — Study a complete full-stack implementation with modern tooling.
Contributors — Add features, fix bugs, or propose improvements.
Browse — Trending, popular, top-rated, now-playing, and upcoming movies.
Search — Full-text search with TMDB integration.
Filter — By genre, release year, rating, and streaming providers.
Details — Cast, trailers, streaming providers, budgets, and revenue.
Similar Movies — AI-powered recommendations via TMDB.
Write Reviews — Rate movies on a 5-star scale with detailed text reviews.
Inline Editing — Edit or delete your reviews without page reload.
Reply Threads — Nested comment system (YouTube-style) with collapse at depth.
Optimistic Updates — Instant UI feedback with background sync.
Role-Based Access — Users manage their own content; admins moderate all.
Authentication — Email/password with Supabase Auth, Google OAuth.
Rate Limiting — Upstash Redis rate limiting to prevent abuse.
CAPTCHA — Cloudflare Turnstile integration for spam protection.
Profile — Manage personal information and view activity.
Watchlist — Save movies to personal watchlist.
Dashboard — Real-time stats (users, reviews, movies, reports).
Content Moderation — Manage reviews, replies, and user reports.
News Management — Create, edit, and publish movie/news articles.
Movie Sync — Manually sync TMDB data for specific movies.
User Management — View and manage registered users.
Auto-Feed — Automated news articles from TMDB movie updates.
Manual Articles — Admin-written news with rich text editor.
Categories — Organized news sections for easy browsing.
Cinematic Dark Theme — Pure black backgrounds with warm gold accents.
Responsive — 5 breakpoints from 375px to 1920px.
Animations — Framer Motion with smooth scroll-reveal and micro-interactions.
Accessibility — WCAG contrast ratios, keyboard navigation, screen reader support.
Performance — Lighthouse scores ≥ 95 across all categories.
Technology
Purpose
Next.js 15 (App Router)
Full-stack React framework with SSR, ISR, and Server Actions
TypeScript (strict)
Type-safe development with zero any types
Node.js 22
JavaScript runtime
Technology
Purpose
Tailwind CSS v4
Utility-first styling with custom design system
Framer Motion
Animations, scroll-reveal, and micro-interactions
React Hook Form + Zod
Form validation and state management
TanStack React Query
Server state management and caching
Zustand
Client state (watchlist, UI preferences)
Technology
Purpose
Supabase
PostgreSQL database, authentication, and storage
Next.js Route Handlers
REST API endpoints
Server Actions
Server-side mutations with revalidation
Upstash Redis
Rate limiting and caching
API
Purpose
TMDB API
Movie catalog, cast, trailers, streaming providers
Google OAuth
Social login via Supabase Auth
Cloudflare Turnstile
CAPTCHA for form spam protection
Tool
Purpose
Vercel
Hosting with ISR and CDN
GitHub Actions
CI/CD pipeline
ESLint + Prettier
Code quality and formatting
Vitest
Unit and integration tests
Playwright
E2E testing
┌──────────────────────────────────────────────────────────────┐
│ Client Layer │
│ ┌──────────────┐ ┌───────────┐ ┌─────────────────────┐ │
│ │ Next.js App │ │ React │ │ Zustand │ │
│ │ Router (SSR) │ │ Query │ │ (Watchlist, UI) │ │
│ └──────────────┘ └───────────┘ └─────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ API Layer │
│ ┌─────────────────┐ ┌─────────────────────────────────┐ │
│ │ Route Handlers │ │ Server Actions │ │
│ │ (REST API) │ │ (submitReview, deleteReview) │ │
│ └─────────────────┘ └─────────────────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ Service Layer │
│ ┌───────────┐ ┌────────────┐ ┌────────────────────────┐ │
│ │ TMDB │ │ Rate │ │ Auth (Supabase) │ │
│ │ Service │ │ Limiter │ │ Session Management │ │
│ └───────────┘ └────────────┘ └────────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ Data Layer │
│ ┌──────────────┐ ┌──────────────────────────────────────┐ │
│ │ Supabase │ │ Upstash Redis │ │
│ │ PostgreSQL │ │ (Rate limiting + Cache) │ │
│ └──────────────┘ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Key Architectural Decisions
Decision
Rationale
Server Components first
Reduce client-side JavaScript, improve SEO and initial load
React Query for client state
Optimistic updates, background refetching, cache invalidation
Supabase RLS
Database-level security — not reliant on client-side checks
ISR for TMDB data
Cache movie pages with 1-hour revalidation
Separate API routes from Server Actions
Route handlers for GET/read operations, Server Actions for POST/write operations
Node.js 22+
npm or pnpm
Supabase project (free tier)
TMDB API key (free)
Upstash Redis (free tier) — for rate limiting
Cloudflare Turnstile (free) — for CAPTCHA
git clone https://github.com/mifdlaldev/cinestack.git
cd cinestack
npm install
2️⃣ Set Up Environment Variables
Copy .env.example to .env.local and fill in your credentials:
cp .env.example .env.local
Variable
Description
Where to Get
NEXT_PUBLIC_SUPABASE_URL
Supabase project URL
Supabase Dashboard → Settings → API
NEXT_PUBLIC_SUPABASE_ANON_KEY
Supabase anon/public key
Supabase Dashboard → Settings → API
TMDB_API_KEY
TMDB API v3 key
TMDB Settings → API
TMDB_READ_ACCESS_TOKEN
TMDB API read token
TMDB Settings → API
UPSTASH_REDIS_REST_URL
Upstash Redis REST URL (optional)
Upstash Console
UPSTASH_REDIS_REST_TOKEN
Upstash Redis token (optional)
Upstash Console
NEXT_PUBLIC_TURNSTILE_SITE_KEY
Cloudflare Turnstile site key (optional)
Cloudflare Dashboard → Turnstile
TURNSTILE_SECRET_KEY
Cloudflare Turnstile secret key (optional)
Cloudflare Dashboard → Turnstile
Note: TMDB and Supabase are required for the app to function. Upstash and Turnstile are optional — the app falls back gracefully.
Run the SQL schema against your Supabase project:
# Option A: Paste into Supabase SQL Editor (recommended)
# Open supabase/schema.sql and copy into https://supabase.com/dashboard/project/your-project/sql/new
# Option B: Using Supabase CLI
supabase db push
4️⃣ Start Development Server
Open http://localhost:3000 — the app should be running.
Command
Description
npm run dev
Start development server
npm run build
Production build
npm run start
Start production server
npm run lint
Run ESLint
cinestack/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (main)/ # Main layout group
│ │ ├── about/ # About page
│ │ ├── actors/ # Actor profiles and search
│ │ ├── admin/ # Admin dashboard panel
│ │ ├── api/ # REST API route handlers
│ │ │ ├── admin/ # Admin API endpoints
│ │ │ ├── auth/ # Auth API (rate limiting)
│ │ │ ├── movies/ # Movie data endpoints
│ │ │ ├── news/ # News CRUD endpoints
│ │ │ ├── reviews/ # Review CRUD endpoints
│ │ │ └── watchlist/ # Watchlist CRUD endpoints
│ │ ├── auth/ # Auth pages (login/register)
│ │ ├── contact/ # Contact page
│ │ ├── discover/ # Movie discovery & filtering
│ │ ├── genre/ # Genre-based browsing
│ │ ├── movies/ # Movie detail pages
│ │ ├── news/ # News portal
│ │ ├── profile/ # User profile
│ │ └── search/ # Search results
│ ├── components/
│ │ ├── layout/ # Layout components (Navbar, Footer, Hero)
│ │ └── ui/ # Reusable UI components
│ ├── lib/ # Utilities and services
│ ├── types/ # TypeScript type definitions
│ └── actions/ # Server Actions
├── supabase/ # Database migrations
│ ├── schema.sql # Full database schema
│ ├── fix-users.sql # User backfill script
│ └── fix-users-rls.sql # RLS policy fixes
├── public/ # Static assets
└── docs/ # Documentation
└── PLAN.md # Project plan and architecture
File
Purpose
src/app/layout.tsx
Root layout with providers (React Query, Auth)
src/components/ui/ReviewSection.tsx
Review system with optimistic updates
src/lib/tmdb.ts
TMDB API client configuration
src/lib/supabase.ts
Supabase server client
src/lib/rate-limiter.ts
Upstash Redis rate limiter
supabase/schema.sql
Complete database schema (idempotent)
Method
Endpoint
Description
GET
/api/reviews?movieId=&page=
List reviews for a movie
PUT
/api/reviews/[id]
Edit review (inline)
POST
/api/reviews/[id]/reply
Reply to review
Method
Endpoint
Description
GET
/api/movies/search?q=
Search movies
GET
/api/movies/discover?
Discover with filters
GET
/api/movies/similar?id=
Similar movies
GET
/api/movies/genres
Movie genres
GET
/api/movies/providers
Streaming providers
Method
Endpoint
Description
GET
/api/watchlist
Get user's watchlist
POST
/api/watchlist
Add to watchlist
DELETE
/api/watchlist/[id]
Remove from watchlist
Method
Endpoint
Description
GET
/api/admin/stats
Dashboard statistics
GET
/api/admin/reviews
Manage all reviews
GET
/api/admin/users
Manage users
CRUD
/api/admin/news
News articles
CRUD
/api/admin/replies
Reply moderation
Table
Purpose
users
User profiles with role (user/admin)
reviews
Movie reviews and ratings (1-10 scale)
watchlists
User movie watchlists
news_articles
News and articles
review_reports
User-generated reports on reviews
RLS (Row Level Security) enabled on all tables
Users can read any profile; edit only their own
Reviews are publicly readable; only owners can edit/delete
Admin actions restricted to users with admin role
Full schema in supabase/schema.sql .
Token
Value
Usage
--color-bg
#000000
Page background
--color-surface
#0a0a0a
Card background
--color-text
#f5f5f1
Primary text (warm white)
--color-accent
#f5c518
Accent (warm gold)
Role
Font
Weight
Display
Archivo Black
900
Body
Inter
400
Mono
JetBrains Mono
400
I welcome contributions! CineStack is designed to be a collaborative project where developers can learn, experiment, and contribute.
Fork the repository
Create a feature branch :
git checkout -b feat/your-feature-name
Make your changes following the existing patterns:
TypeScript strict mode — no any types
Server Components first, Client Components only when needed
Optimistic updates for mutations
Accessible and responsive UI
Commit with Conventional Commits :
git commit -m " feat: add your feature"
Push and open a Pull Request :
git push origin feat/your-feature-name
# Then open a PR on GitHub
Code Style : ESLint + Prettier, 2-space indentation, single quotes
Components : Keep focused; extract reusable logic to lib/
State : Server Components for static data, React Query for dynamic data, Zustand for UI
Database : Parameterized queries via Supabase SDK
Security : No hardcoded secrets; environment variables for all sensitive data
Phase 1 — Foundation ✅
Next.js 15, TypeScript, Supabase, TMDB integration, movie catalog, auth
Phase 2 — Interaction ✅
Reviews, ratings, reply threads, optimistic updates, rate limiting, CAPTCHA
Phase 3 — Administration ✅
Admin dashboard, content moderation, news management, user management
Phase 4 — Polish 🔄
Lighthouse ≥ 95, tests, documentation, performance optimization
Phase 5 — Future 🚀
Theme toggle, recommendations, social features, PWA, mobile app, i18n