{"id":47032520,"url":"https://github.com/mchestr/plex-manager","last_synced_at":"2026-03-12T00:09:39.974Z","repository":{"id":324649230,"uuid":"1097753492","full_name":"mchestr/plex-manager","owner":"mchestr","description":null,"archived":false,"fork":false,"pushed_at":"2025-12-30T05:58:59.000Z","size":7321,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-02T13:20:31.731Z","etag":null,"topics":["ai","jellyseerr","openai","plex","plex-media-server","tautulli","wrapped"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mchestr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-16T19:05:01.000Z","updated_at":"2025-12-30T05:59:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mchestr/plex-manager","commit_stats":null,"previous_names":["mchestr/plex-wrapped"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mchestr/plex-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchestr%2Fplex-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchestr%2Fplex-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchestr%2Fplex-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchestr%2Fplex-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mchestr","download_url":"https://codeload.github.com/mchestr/plex-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchestr%2Fplex-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30408011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T22:36:59.286Z","status":"ssl_error","status_checked_at":"2026-03-11T22:36:57.544Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","jellyseerr","openai","plex","plex-media-server","tautulli","wrapped"],"created_at":"2026-03-12T00:09:39.268Z","updated_at":"2026-03-12T00:09:39.958Z","avatar_url":"https://github.com/mchestr.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Plex Management System\n\n\u003e **WARNING: This project is a Work In Progress (WIP)**\n\u003e\n\u003e This project is currently under active development. Features may be incomplete, unstable, or subject to change. Use at your own risk.\n\n**The ultimate companion for your Plex Media Server.**\n\nPlex Management System transforms your Plex experience by combining powerful management tools, community features, and personalized insights into a single platform. It helps users configure their clients for optimal playback, manage media requests, report issues, and celebrate their viewing habits with \"Plex Wrapped\".\n\n## Screenshots\n\n\u003cdiv align=\"center\"\u003e\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n**Home Dashboard**\n\n![Home Page](docs/images/home.png)\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\n**Wrapped Viewer**\n\n![Wrapped Viewer](docs/images/wrapped-viewer.png)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n**Setup Wizard**\n\n![Setup Wizard](docs/images/setup.png)\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\n**Admin Dashboard**\n\n![Admin Dashboard](docs/images/admin-dashboard.png)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c/div\u003e\n\n---\n\n## Features\n\n### 🚀 Onboarding \u0026 Configuration\n- **Guided Onboarding** for new users to the server\n- **Client Configuration Guides** to ensure Direct Play and best quality\n- **Issue Reporting** workflow to streamline support requests\n- **Media Request** integration (via Overseerr)\n- **Discord Integration** for community engagement and announcements (optional)\n- **Service Status** monitoring for all connected platforms\n\n### 📊 Plex Wrapped \u0026 Statistics\n- **Total watch time** breakdown (movies vs. shows)\n- **Top movies and shows** with play counts and ratings\n- **Server-wide leaderboards** to see how you rank\n- **Visualizations** with animated charts and transitions\n- **AI-Powered Insights** for personalized viewing summaries\n\n### 🤝 Share \u0026 Discover\n- **One-click sharing** of wrapped stats\n- **Public share links** for easy social media sharing\n- **Analytics tracking** for shared content\n- **Responsive design** that works on any device\n\n### 🛠️ Admin Features\n- **User management** dashboard with role-based access control\n- **Service management** - Monitor and configure Plex, Tautulli, Overseerr, Sonarr, Radarr\n- **Announcements system** - Server-wide notifications with markdown support\n- **LLM usage tracking** and cost monitoring\n- **Share analytics** to see what's popular\n- **Audit logging** for security and compliance\n- **Centralized configuration** for all integrations\n\n---\n\n## Quick Start\n\n### Prerequisites\n\n- **Node.js** 18+ (LTS recommended)\n- **npm** or **yarn**\n- **PostgreSQL** database (SQLite is no longer supported as of Prisma v7)\n- Access to:\n  - A **Plex server** (with admin token)\n  - **Tautulli** instance (for viewing statistics)\n  - **Overseerr** (optional, for request stats)\n  - **Sonarr/Radarr** (optional, for media management features)\n  - **OpenAI** API key (optional, for AI insights)\n\n### Installation\n\n1. **Clone the repository**\n```bash\ngit clone \u003crepository-url\u003e\ncd plex-wrapped\n```\n\n2. **Install dependencies**\n```bash\nnpm install\n```\n\n3. **Set up environment variables**\n```bash\ncp example.env .env\n```\n\nEdit `.env` and configure:\n- `DATABASE_URL` - PostgreSQL connection string (e.g., `postgresql://user:password@localhost:5432/plex_manager`)\n- `NEXT_PUBLIC_APP_URL` - Your public application URL (e.g., `http://localhost:3000` for dev, `https://yourdomain.com` for production)\n- `NEXTAUTH_URL` - Your application URL for NextAuth callbacks (should match `NEXT_PUBLIC_APP_URL` in production)\n- `NEXTAUTH_SECRET` - Generate with: `openssl rand -base64 32`\n- `PLEX_CLIENT_IDENTIFIER` - Unique identifier for your app instance (any string, doesn't need to be a UUID)\n\n4. **Initialize the database**\n```bash\nnpm run db:generate\nnpm run db:push\n```\n\n5. **Start the development server**\n```bash\nnpm run dev\n```\n\n6. **Open your browser**\nNavigate to [http://localhost:3000](http://localhost:3000)\n\n7. **Complete the setup wizard**\nOn first launch, you'll be guided through configuring:\n- Plex server connection (URL format: `https://example.com:32400`)\n- Tautulli integration (URL format: `http://example.com:8181`)\n- Overseerr integration (optional, URL format: `http://example.com:5055`)\n- LLM provider (optional)\n\n---\n\n## Development\n\n### Project Structure\n\n```\nplex-wrapped/\n├── app/                    # Next.js App Router (pages, layouts, routes)\n│   ├── (app)/              # Authenticated app layout group\n│   ├── admin/              # Admin dashboard and management\n│   ├── api/                # API routes (webhooks, external integrations)\n│   ├── auth/               # Authentication pages\n│   ├── onboarding/         # User onboarding flow\n│   ├── setup/              # Initial setup wizard\n│   └── wrapped/            # Wrapped viewer and sharing\n├── actions/                # Server Actions (mutations, data operations)\n├── components/             # React components\n│   ├── admin/              # Admin-specific components\n│   ├── generator/          # Wrapped generation UI\n│   ├── onboarding/         # Onboarding components\n│   ├── setup-wizard/       # Setup wizard steps\n│   ├── ui/                 # Shared UI primitives\n│   └── wrapped/            # Wrapped display components\n├── lib/                    # Utilities, helpers, business logic\n│   ├── connections/        # External API clients (Plex, Tautulli, Overseerr, etc.)\n│   ├── security/           # Security utilities (rate limiting, CSRF, audit logging)\n│   ├── validations/        # Zod schemas for all services\n│   ├── wrapped/            # Wrapped generation and statistics\n│   └── utils/              # Shared utilities\n├── types/                  # TypeScript type definitions\n├── prisma/                 # Database schema and migrations\n└── e2e/                    # Playwright end-to-end tests\n```\n\n### Available Scripts\n\n| Command | Description |\n|---------|-------------|\n| `npm run dev` | Start development server |\n| `npm run build` | Build for production |\n| `npm run start` | Start production server |\n| `npm run lint` | Run ESLint |\n| `npm test` | Run unit/integration tests |\n| `npm run test:watch` | Run tests in watch mode |\n| `npm run test:coverage` | Generate coverage report |\n| `npm run test:e2e` | Run end-to-end tests (Playwright) |\n| `npm run test:e2e:ui` | Run E2E tests in UI mode |\n| `npm run db:generate` | Generate Prisma Client |\n| `npm run db:push` | Push schema changes to database |\n| `npm run db:migrate` | Run database migrations |\n| `npm run db:studio` | Open Prisma Studio (database GUI) |\n| `npm run db:seed` | Seed database with test data |\n\n### Development Guidelines\n\n**📖 For comprehensive development guidelines, see [CLAUDE.md](CLAUDE.md)**\n\nThe CLAUDE.md file contains detailed information about:\n- Architecture patterns and component design\n- Server Actions vs API routes\n- Database patterns with Prisma\n- Integration guides (Plex, Tautulli, Overseerr, Sonarr/Radarr)\n- Security best practices\n- Testing strategies\n- Code style conventions\n\n#### **Quick Reference**\n\n**Architecture Principles**\n- **Server Components by default** - Use Client Components (`'use client'`) only when needed\n- **Server Actions** - Prefer Server Actions over API routes for mutations\n- **TanStack Query** - Use for all client-side data fetching\n- **TypeScript strict mode** - Maintain type safety with exhaustive checks\n\n**Code Style**\n- **Tailwind CSS** - Use utility classes over custom CSS\n- **Zod** - Validate all user inputs and API responses\n- **Error boundaries** - Implement proper error handling and loading states\n- **Component organization** - Keep components focused and reusable (max ~200-300 lines)\n- **Avoid over-engineering** - Implement exactly what's needed, no premature abstractions\n\n**Testing**\n- **Jest** - Unit and integration tests with comprehensive coverage\n- **Testing Library** - Component testing utilities\n- **Playwright** - E2E testing with authenticated sessions (use `data-testid` selectors)\n- See [E2E Testing Guide](e2e/README.md) for authenticated session patterns\n\n**Logging**\n- Use the `createLogger` utility from `@/lib/utils/logger`\n- See [Logging Guide](docs/logging.md) for details on log levels, metadata, and best practices\n\n### Database Management\n\n```bash\n# Generate Prisma Client after schema changes\nnpm run db:generate\n\n# Push schema changes (development)\nnpm run db:push\n\n# Create migration (production)\nnpm run db:migrate\n\n# Open database GUI\nnpm run db:studio\n```\n\n### Environment Variables\n\nSee `example.env` for all available configuration options. Key variables:\n\n- **Database**: `DATABASE_URL`\n- **Application URLs**: `NEXT_PUBLIC_APP_URL` (preferred, used for public URLs), `NEXTAUTH_URL` (required by NextAuth, should match `NEXT_PUBLIC_APP_URL` in production)\n- **Authentication**: `NEXTAUTH_SECRET`, `PLEX_CLIENT_IDENTIFIER`\n- **Development**: `DEV_*` variables for setup wizard defaults\n  - Use URL format: `DEV_PLEX_URL=\"https://localhost:32400\"` (includes protocol and port)\n\n---\n\n## Deployment\n\n### Production Deployment Requirements\n\nWhen deploying to production, ensure the following environment variables are set:\n\n1. **`NEXT_PUBLIC_APP_URL`** - Your public-facing domain (e.g., `https://yourdomain.com`)\n   - Used for sharing links, OG images, and public URLs\n   - Must be accessible from the internet\n\n2. **`NEXTAUTH_URL`** - Your application URL (should match `NEXT_PUBLIC_APP_URL`)\n   - Used by NextAuth for OAuth callbacks and session management\n   - Must match the domain where your app is accessible\n\n3. **`NEXTAUTH_SECRET`** - A secure random string\n   - Generate with: `openssl rand -base64 32`\n   - Keep this secret and never commit it to version control\n\n4. **`DATABASE_URL`** - Your production PostgreSQL database connection string\n   - Example: `postgresql://user:password@host:port/database`\n   - SQLite is no longer supported (Prisma v7 requirement)\n\n### Important Notes\n\n- **No hardcoded localhost**: The application will throw an error in production if neither `NEXT_PUBLIC_APP_URL` nor `NEXTAUTH_URL` is set\n- **HTTPS required**: In production, always use HTTPS URLs for both environment variables\n- **Domain consistency**: Both URL variables should point to the same domain to avoid authentication issues\n\n### Docker Deployment\n\nThe project includes a `Dockerfile` for containerized deployments. When deploying with Docker:\n\n1. Set environment variables in your deployment platform or `.env` file\n2. Ensure `NEXT_PUBLIC_APP_URL` and `NEXTAUTH_URL` are set to your production domain\n3. The application will fail to start in production mode if these are not configured\n\n---\n\n## Tech Stack\n\n| Category | Technology |\n|----------|-----------|\n| **Framework** | Next.js 14+ (App Router) |\n| **Language** | TypeScript (strict mode) |\n| **Database** | Prisma v7 + PostgreSQL |\n| **Authentication** | NextAuth.js (Plex PIN-based authentication) |\n| **Data Fetching** | TanStack Query (React Query) |\n| **Styling** | Tailwind CSS |\n| **Animations** | Framer Motion |\n| **Validation** | Zod |\n| **Testing** | Jest + Testing Library + Playwright |\n\n---\n\n## How It Works\n\n1. **User Authentication** - Sign in with your Plex account using PIN-based authentication\n2. **Onboarding** - New users are guided through server configuration and features\n3. **Data Collection** - Fetch viewing statistics from Tautulli and Plex\n4. **Dashboard** - View server info, request media, and explore content\n5. **Plex Wrapped** - Generate shareable year-end summaries (optional)\n\n---\n\n## Integrations\n\nThe platform integrates with multiple services to provide a comprehensive Plex management experience:\n\n### Core Services\n- **Plex Media Server** - Primary media server integration (required)\n- **Tautulli** - Watch history and statistics tracking (required for Wrapped features)\n\n### Optional Services\n- **Overseerr** - Media request management and availability tracking\n- **Sonarr** - TV series management and monitoring\n- **Radarr** - Movie management and monitoring\n- **Discord** - Bot integration for server announcements and community features\n- **OpenAI/LLM Providers** - AI-powered insights for Wrapped summaries\n\nAll integrations are configured through the setup wizard or admin panel, with validation and connection testing built-in.\n\n---\n\n## Security\n\n- **PIN-based authentication** via Plex\n- **Server access verification** - Only users with access to your Plex server can sign in\n- **Secure token generation** for sharing features\n- **Admin-only actions** protected by role checks\n- **Input validation** with Zod schemas on all user inputs and API responses\n- **SQL injection protection** via Prisma parameterized queries\n- **XSS prevention** - React escapes by default, no unsafe HTML rendering\n- **CSRF protection** - Built into Next.js Server Actions\n- **Rate limiting** - Protection for sensitive endpoints\n- **Audit logging** - Tracking of admin actions and security events\n\nSee [CLAUDE.md](CLAUDE.md) for detailed security best practices.\n\n---\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n---\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n---\n\n## Acknowledgments\n\nInspired by Spotify Wrapped. Built for the Plex community.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmchestr%2Fplex-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmchestr%2Fplex-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmchestr%2Fplex-manager/lists"}