Your Personal Premium Streaming Dashboard & Media Library Manager
Strive is a modern, feature-rich web application designed for movie and TV show enthusiasts. It provides a centralized, private, ad-free repository to discover content, manage custom watchlists, track TV episode progress, and synchronize data across platforms. Built with a full-stack approach using React, Firebase, Vercel Serverless Functions, and the TMDb API.
- Overview
- Features
- Tech Stack
- Architecture
- Folder Structure
- Installation & Setup
- Environment Variables
- Scripts
- Configuration
- API Integrations
- Project Workflow
- State Management
- Performance Optimizations
- Security
- Deployment
- Future Improvements
- Contributing
- License
What problem this solves: Managing a personal media catalog across various streaming services is fragmented. Users find it difficult to track what they want to watch, where they left off in a TV series, and maintain a unified library. Standard applications are often commercialized, lack custom grouping, or lock in user data.
Why it exists: Strive was built to provide a clean, unified, ad-free media library manager. It prioritizes data portability (CSV imports/exports), detailed TV show tracking (episode-level matrices), and local-first responsiveness.
Who it is for: Cinephiles, series binge-watchers, power users who prefer CSV management, and Simkl users looking for a private, synchronized library dashboard.
- Secure Sign-in: Powered by Firebase Authentication.
- Private Workspaces: Each user gets an isolated Firestore environment for their library and settings.
- Serverless Data Protection: Critical operations (like TV progress tracking) are locked down and handled securely via Vercel Serverless API using Firebase Admin credentials.
- Centralized Catalog: Save movies and TV shows to a primary library.
- Custom Lists: Create, name, pin, and manage unlimited personal lists (e.g., "Favorite Sci-Fi", "Weekend Binges").
- Watch Status Tracking: Mark items as "Plan to Watch", "Watching", "Completed", or "Dropped".
- Episode Matrix: A visual grid dashboard of seasons and episodes.
- Granular Logging: Check off individual episodes and track watch history.
- Auto-Calculated Progress: Automatically computes completion percentages, aired episodes versus watched, and the "Next to Watch" episode.
- CSV Export: Download any list as a portable CSV file.
- Smart CSV Import: Upload CSVs with automatic TMDb/IMDb matching, fallback manual searching, and batch processing.
- Dynamic Feeds: Browse Now Playing, Popular, Top Rated, and Upcoming content.
- Universal Debounced Search: Real-time multi-category search spanning movies and TV series.
- Detailed Media Views: High-quality posters, backdrops, synopses, cast listings, and integrated trailers.
- Simkl Synchronization: Connect a Simkl account to sync scrobbles and watch history automatically.
- IMDb Ratings Enrichment: Fuses TMDb metadata with highly accurate IMDb audience scores.
- Glassmorphism & Animations: Fluid page transitions and micro-interactions powered by Framer Motion.
- Responsive Layouts: Tailored experiences for mobile, tablet, and desktop using Tailwind CSS.
- Integrated Video Player: A built-in player interface with multi-server fallback support.
| Category | Technology |
|---|---|
| Frontend | React 19, Vite |
| Routing | React Router DOM |
| State Management | Redux Toolkit (Slices, Thunks) |
| Styling | Tailwind CSS v4, Vanilla CSS |
| Animation | Framer Motion |
| Backend API | Node.js, Vercel Serverless Functions |
| Database | Firebase Firestore (NoSQL) |
| Authentication | Firebase Auth |
| External APIs | TMDb, IMDb, Simkl |
| Utilities | PapaParse (CSV), Busboy (Multipart forms), Axios |
Strive follows a clean, tiered architecture where data flows unidirectionally from services to UI components.
graph TD
UI[React Web App] --> State[Redux Store & Hooks]
State --> FBClient[Firebase Client SDK]
State --> VercelAPI[Vercel Serverless API]
FBClient --> Firestore[(Firestore DB)]
VercelAPI --> FBAdmin[Firebase Admin SDK]
FBAdmin --> Firestore
VercelAPI --> TMDb[TMDb API]
VercelAPI --> IMDb[IMDb API]
UI --> Simkl[Simkl API]
- UI Layer: Pages, Modals, Shared Panels (BottomNav, EpisodeMatrixView).
- State Layer: Redux Store (
userSlice,listsSlice,simklSlice, etc.). - Business Logic: Custom Hooks (
useSeriesTracking,useImdbRating) and Adapters. - Data Layer: Firestore Client SDK for direct client-authorized reads/writes.
- Infrastructure Layer: Vercel Serverless Functions handling privileged operations (e.g., episode watch logs, CSV batch parsing) via the Firebase Admin SDK.
strive/
โโโ api/ # Vercel Serverless Functions (Backend)
โ โโโ _lib/ # Shared backend utilities, middleware, and adapters
โ โโโ lists/ # Endpoints for CSV import/export & enrichment
โ โโโ movie/ # Endpoints for movie details
โ โโโ tv/ # Endpoints for TV details, episodes, videos
โ โโโ markEpisodeWatched.js # Critical endpoint for TV progress tracking
โโโ docs/ # Comprehensive technical documentation & guides
โโโ public/ # Static public assets
โโโ scripts/ # Maintenance scripts (backfill, database repair)
โโโ src/ # React Frontend Source
โโโ assets/ # Local images and icons
โโโ components/ # UI Components (auth, layout, library, lists, media)
โโโ domain/ # Domain models and business logic adapters
โโโ hooks/ # Custom React Hooks for state and data fetching
โโโ js/ # Vanilla JavaScript utilities (e.g., player logic)
โโโ services/ # Services for Firestore CRUD, TMDb, IMDb, Simkl
โโโ styles/ # Global and component-specific CSS
โโโ util/ # Utilities (Redux store setup, Firebase init)
โโโ App.jsx # Main App entry and global event listeners
โโโ main.jsx # React DOM render entry
1. Clone the repository
git clone https://github.com/CoffeePatch/StrIve.git
cd strive2. Install dependencies
npm install3. Configure Environment Variables
Copy .env.example to .env and populate the required keys (see Environment Variables).
4. Start the development server
npm run devThe app will be available at http://localhost:5173.
5. Build for production
npm run buildCreate a .env or .env.local file with the following variables. Never commit your actual .env file containing secrets.
| Variable | Purpose |
|---|---|
VITE_FIREBASE_API_KEY |
Firebase Client API Key. |
VITE_FIREBASE_AUTH_DOMAIN |
Firebase Client Auth Domain. |
VITE_FIREBASE_PROJECT_ID |
Firebase Project ID. |
VITE_FIREBASE_STORAGE_BUCKET |
Firebase Storage Bucket. |
VITE_FIREBASE_MESSAGING_SENDER_ID |
Firebase Messaging Sender ID. |
VITE_FIREBASE_APP_ID |
Firebase App ID. |
TMDB_API_KEY |
Used by serverless API to query TMDb. |
TMDB_READ_ACCESS_TOKEN |
Used by serverless API for authenticated TMDb requests. |
FIREBASE_PROJECT_ID |
Used by Firebase Admin SDK in serverless API. |
FIREBASE_CLIENT_EMAIL |
Service Account Email for Firebase Admin SDK. |
FIREBASE_PRIVATE_KEY |
Service Account Private Key for Firebase Admin SDK. |
VITE_USE_FIRESTORE_EMULATOR |
(Optional) Set to true to use local emulator. |
| Script | Command | Description |
|---|---|---|
| dev | vite |
Starts the Vite development server. |
| build | vite build |
Compiles and bundles the application for production. |
| lint | eslint . |
Runs ESLint to check for code quality and styling issues. |
| preview | vite preview |
Serves the production build locally for testing. |
vite.config.js: Configures the Vite bundler, React plugins, Tailwind CSS integration, bundle visualizer, and sets up local API proxying (/apitolocalhost:3000).vercel.json: Defines the Vercel deployment configuration, routing rules for single-page applications, serverless API rewrites, and CORS headers.firebase.json: Outlines Firebase Hosting, Functions, and Emulator settings. Points to Firestore security rules (firestore.rules) and indexes (firestore.indexes.json).firestore.rules: A comprehensive security model that restricts client access. Ensures users only read/write their own library documents while explicitly denying client writes to criticalepisode_statesandseries_progresspaths (enforcing server-side validation).eslint.config.js: Uses the flat config format to enforce modern JavaScript and React Hooks best practices.
- Role: Primary source of truth for media catalogs, searches, posters, and cast lists.
- Integration: Accessed securely via Vercel serverless proxy endpoints (
/api/tmdb,/api/movie/details,/api/tv/details). - Handling: Implements rate limiting protection, caching, and concurrent request limits (using
pLimit).
- Role: Enriches library items with high-quality audience scores.
- Integration: Mapped via TMDb external IDs and fetched via a custom/fallback API endpoint.
- Handling: Ratings are locally cached in Firestore (
imdb_cache/{tmdbId}) to drastically reduce API hits and improve load times.
- Role: Provides 2-way watch history synchronization and active playback scrobbling.
- Integration: OAuth-based authentication, background polling for sync activities, and batch updating library statuses based on external watch events.
How data moves during a core user action (e.g., Marking a TV episode as watched):
sequenceDiagram
participant User
participant UI as React Component
participant Hook as useSeriesTracking
participant API as Serverless API
participant DB as Firestore (Admin)
User->>UI: Clicks "Watched" on Episode 3
UI->>Hook: Triggers mutation
Hook->>API: POST /api/markEpisodeWatched
API->>API: Verify Auth Token
API->>DB: Start Transaction
DB-->>API: Read current progress
API->>API: Calculate new progress & Next Episode
API->>DB: Write Episode Log & Update Library Item
DB-->>API: Transaction Success
API-->>Hook: 200 OK
Hook-->>UI: Update State
UI-->>User: Visual checkmark & progress bar fills
Strive relies on a robust combination of local UI state and global Redux slices:
- Redux Toolkit (
appStore.js):userSlice: Manages active user session and profile data.listsSlice: Caches custom lists, active list items, and handles batch thunks for list additions/deletions.moviesSlice/tvShowsSlice: Caches discovery feeds (Popular, Top Rated, Now Playing) to prevent redundant API fetches on route changes.simklSlice: Manages Simkl authentication status, sync history, and background scrobble states.
- React Context / Local State: Used for ephemeral UI states like modal visibility, search debouncing, and filter selections.
- Real-time Listeners: Custom hooks (e.g.,
useEpisodeStates,useSeriesProgress) establish directonSnapshotconnections to Firestore, bypassing Redux for instantaneous updates when data changes server-side.
Strive is engineered for speed and low database reads to stay within Firebase hobby tier limits:
- Document Caching: IMDb ratings are cached in an
imdb_cachecollection, eliminating repetitive external API calls across users. - Debounced Input: Search fields use a 500ms debounce (
useSearchhook) to prevent spamming the TMDb API. - Memoization: Heavy list filtering and sorting calculations utilize
useMemoto prevent UI blocking during renders. - Single Source of Truth: The database avoids data duplication. A single
library_itemsdocument tracks all list memberships via arrays, preventing multiple document reads. - Serverless Transactions: Complex operations involving multiple document updates (like TV progress tracking) are processed in bulk server-side, reducing client-side processing and network roundtrips.
- Batch Processing: CSV imports chunk and process requests concurrently (e.g., max 10 concurrent TMDb requests) to avoid timeouts and rate limits.
- Authentication: All private routes are guarded by a
ProtectedRoutecomponent that forces Firebase authentication. - Authorization: Firestore Security Rules strictly enforce that
request.auth.uid == uidfor all read/write operations on user data. - Protected Database Paths: Sensitive collections like
episode_statesandseries_progresscompletely reject client writes. They can only be modified by the serverless API using a verified Firebase Admin token. - API Security: The Vercel API validates Firebase ID tokens via custom middleware (
authMiddleware.js) before executing any mutative actions. - Secret Management: API keys for TMDb and Firebase Admin are stored exclusively in backend environment variables and are never exposed to the client bundle.
Strive is designed for a split deployment model (though primarily hosted on Vercel):
- Frontend Hosting & Serverless API: Deployed on Vercel.
- Vercel automatically builds the Vite app and serves the
/apidirectory as Serverless Functions. vercel.jsonconfigures the necessary rewrites and CORS headers.
- Vercel automatically builds the Vite app and serves the
- Database & Auth: Hosted on Firebase.
- Firestore holds the NoSQL database.
- Firebase Auth handles identity management.
Production Workflow:
Pushing to the main branch triggers an automatic build and deployment pipeline on Vercel.
Based on the current architecture, potential future enhancements could include:
- AI-Powered Recommendations: Generating personalized suggestions based on library contents and watch history.
- Social Features: Public user profiles and the ability to share or clone custom lists.
- Enhanced Data Visualizations: A dashboard for watching habits and statistics (e.g., time watched per genre).
- PWA Support: Adding a web manifest and service workers for native-like offline capabilities.
(Note: These are future ideas and are not currently implemented.)
Contributions are welcome! If you have suggestions for improvements or want to add new features:
- Fork the repository.
- Create your feature branch:
git checkout -b feature/AmazingFeature - Commit your changes:
git commit -m 'Add some AmazingFeature' - Push to the branch:
git push origin feature/AmazingFeature - Open a Pull Request.
This project is licensed under the MIT License. See the LICENSE file for details.