A modern, dark-themed administrative dashboard built with Next.js 16+, Supabase, Tailwind CSS, and shadcn/ui components. Full CRUD API for managing Episodes and Polls with real-time data updates.
- 🔐 Supabase Authentication - Secure login with single static user support
- 🎨 Dark Theme UI - Futuristic dark interface with teal neon accents
- 📊 Real-time Dashboard - Live statistics for Episodes and Polls with shimmer loaders
- 📱 Fully Responsive - Works seamlessly on desktop and mobile devices
- 🗂️ Complete CRUD Operations:
- Episodes: Create, Read, Update, Delete with full metadata support
- Polls: Create, Read, Update, Delete with dynamic options
- 🎯 Interactive Polls - Real-time voting with optimistic UI updates
- 📈 Data Visualization - Charts using Recharts
- 🔔 Toast Notifications - User feedback for all CRUD operations
- ⚡ Shimmer Loaders - Beautiful loading states throughout the app
- 🎬 Episode Management - Comprehensive episode editor with media assets
- 📝 Poll Management - Dynamic poll creation with customizable options
- Framework: Next.js 16.1+ (App Router)
- Database: Supabase (PostgreSQL)
- Authentication: Supabase Auth
- Styling: Tailwind CSS 4.0
- UI Components: shadcn/ui (Radix UI)
- Charts: Recharts
- Icons: Lucide React
- State Management: React Context API
- Form Handling: React Hooks
- Node.js 18+ installed
- npm or yarn package manager
- Supabase account and project
git clone <repository-url>
cd admin-os-dashboardnpm installCreate a .env.local file in the root directory:
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your_supabase_anon_key
# Authentication (Static User)
NEXT_PUBLIC_STATIC_ADMIN_EMAIL=admin@example.com
NEXT_PUBLIC_STATIC_ADMIN_PASSWORD=your_secure_password
# Optional: For user creation scripts
SUPABASE_SERVICE_ROLE_KEY=your_service_role_keyGetting Supabase Credentials:
- Go to Supabase Dashboard
- Select your project or create a new one
- Go to Settings → API
- Copy the following:
- Project URL →
NEXT_PUBLIC_SUPABASE_URL - anon/public key →
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY - service_role key →
SUPABASE_SERVICE_ROLE_KEY(for scripts only)
- Project URL →
Run the database migration in your Supabase Dashboard:
- Go to SQL Editor in Supabase Dashboard
- Run the contents of
supabase/migrations/create_tables.sql - Or use Supabase CLI:
supabase db execute --file supabase/migrations/create_tables.sqlThis creates the following tables:
episodes- Episode data with full metadatapolls- Poll data linked to episodespoll_options- Dynamic poll options with vote counts
Run the user creation script:
node scripts/create-user-simple.jsOr manually create a user in Supabase Dashboard → Authentication → Users
npm run devOpen http://localhost:3000 in your browser
npm run build
npm startadmin-os-dashboard/
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── api/ # API Routes
│ │ │ ├── episodes/ # Episodes API endpoints
│ │ │ │ ├── route.js # GET, POST /api/episodes
│ │ │ │ └── [id]/ # GET, PUT, DELETE /api/episodes/:id
│ │ │ └── polls/ # Polls API endpoints
│ │ │ ├── route.js # GET, POST /api/polls
│ │ │ └── [id]/ # GET, PUT, DELETE /api/polls/:id
│ │ ├── page.js # Login page (root route)
│ │ ├── dashboard/ # Dashboard with analytics
│ │ ├── episodes/ # Episode Management page
│ │ ├── create-episode/ # Create/Edit Episode page
│ │ ├── polls/ # Poll Management page
│ │ │ └── [id]/ # Poll Details & Voting page
│ │ ├── create-poll/ # Create Poll page
│ │ ├── layout.js # Root layout with providers
│ │ └── globals.css # Global styles
│ ├── components/
│ │ ├── dashboard/ # Dashboard components
│ │ │ ├── episode-stats-card.jsx
│ │ │ ├── poll-stats-card.jsx
│ │ │ ├── dashboard-analytics.jsx
│ │ │ ├── google-analytics-kpi.jsx
│ │ │ ├── social-media-stats.jsx
│ │ │ ├── chart-row.jsx
│ │ │ └── metrics-referrals.jsx
│ │ ├── layout/ # Layout components
│ │ │ ├── header.jsx # App header with user menu
│ │ │ ├── sidebar.jsx # Navigation sidebar
│ │ │ └── main-layout.jsx # Main layout wrapper
│ │ ├── shimmer/ # Loading shimmer components
│ │ │ ├── episode-stats-card-shimmer.jsx
│ │ │ ├── poll-stats-card-shimmer.jsx
│ │ │ ├── google-analytics-kpi-shimmer.jsx
│ │ │ ├── social-media-stats-shimmer.jsx
│ │ │ ├── chart-row-shimmer.jsx
│ │ │ ├── metrics-referrals-shimmer.jsx
│ │ │ ├── episodes-table-shimmer.jsx
│ │ │ ├── polls-table-shimmer.jsx
│ │ │ └── poll-details-shimmer.jsx
│ │ └── ui/ # shadcn/ui components
│ │ ├── button.jsx
│ │ ├── card.jsx
│ │ ├── dialog.jsx
│ │ ├── input.jsx
│ │ ├── toast.jsx # Toast notification system
│ │ └── ...
│ ├── context/
│ │ └── AuthContext.jsx # Authentication context
│ ├── hooks/
│ │ └── useAuth.js # Authentication hook
│ ├── lib/
│ │ ├── supabase-client.js # Client-side Supabase client
│ │ ├── supabase-server.js # Server-side Supabase client
│ │ ├── db-helpers.js # Database helper functions
│ │ └── utils.js # Utility functions
│ └── data/ # Static JSON data (legacy)
│ ├── dashboard.json
│ ├── episodes.json
│ └── polls.json
├── supabase/
│ └── migrations/
│ └── create_tables.sql # Database schema
├── scripts/ # Utility scripts
│ ├── create-user.js # User creation script
│ └── create-user-simple.js # Simple user creation
├── middleware.ts # Route protection middleware
├── package.json
├── tailwind.config.js
├── next.config.js
└── jsconfig.json
- Login page with Supabase authentication
- Static user validation before Supabase sign-in
- Session persistence across page refreshes
- Redirects to
/dashboardafter successful login - Redirects authenticated users away from login page
- Real-time Statistics:
- Total Episodes with breakdown (Available, Draft, Upcoming)
- Available Episodes count
- Total Polls with breakdown (Live, Draft, Ended)
- Total Poll Votes across all polls
- Analytics Components:
- Google Analytics KPIs
- Social Media Statistics
- Daily Signal Traffic Chart (Area Chart)
- Demographics Pie Chart
- Metrics and Top Referral Nodes
- Shimmer loaders during data fetching
- Dynamic episode listing from Supabase
- Table view with sorting and filtering
- Status badges (Available, Upcoming, Locked, Draft)
- View episode details in modal
- Edit episode functionality with form validation
- Delete episode with confirmation
- Shimmer loaders during loading
- Comprehensive episode editor:
- Basic Information: Title, description, episode/season numbers
- Publishing & Visibility: Visibility status, access level, release datetime
- Media Assets: Thumbnail, banner, video, audio URLs
- Metadata: Tags, genres, runtime, clearance level
- Settings: Age restriction, notifications
- Save draft and deploy live actions
- Form validation with error messages
- Toast notifications for success/error
- Dynamic poll listing from Supabase
- Poll status and vote counts
- Filter by episode and status
- View, edit, and delete operations
- Shimmer loaders during loading
- Real-time updates after CRUD operations
- Individual poll view page
- Interactive voting interface
- Real-time vote updates with optimistic UI
- Progress bars showing vote percentages
- Poll information sidebar
- Shimmer loader during loading
- Dynamic poll creation form
- Episode selection (fetched from API)
- Poll title and description
- Dynamic poll options (add/remove)
- Duration configuration
- Save as draft or deploy live
- Form validation
- Toast notifications
GET /api/episodes- Get all episodes (with filtering & pagination)POST /api/episodes- Create new episode (requires auth)GET /api/episodes/[id]- Get single episodePUT /api/episodes/[id]- Update episode (requires auth)DELETE /api/episodes/[id]- Delete episode (requires auth)
Query Parameters:
visibility- Filter by visibility (AVAILABLE, UPCOMING, LOCKED, DRAFT, ARCHIVED)access_level- Filter by access level (free, premium, vip)status- Filter by status (DRAFT, PUBLISHED)limit- Results per page (default: 100)offset- Pagination offset (default: 0)
GET /api/polls- Get all polls (with filtering & pagination)POST /api/polls- Create new poll with options (requires auth)GET /api/polls/[id]- Get single poll with optionsPUT /api/polls/[id]- Update poll (requires auth)DELETE /api/polls/[id]- Delete poll (requires auth)
Query Parameters:
episode_id- Filter by episode UUIDstatus- Filter by status (DRAFT, LIVE, ENDED, ARCHIVED)limit- Results per page (default: 100)offset- Pagination offset (default: 0)
API Documentation: See doc/API_DOCUMENTATION.md for detailed API documentation.
The application uses Supabase Authentication with a static user validation approach:
- Static Validation: Email and password are validated against environment variables before Supabase authentication
- Supabase Session: Valid credentials create a Supabase session
- Context API: Authentication state is managed globally via
AuthContext - Route Protection: Middleware protects routes based on authentication status
Protected Routes:
/dashboard/admin/episodes/create-episode/polls/create-poll
Public Routes:
//about/login
Modular dashboard components for better maintainability:
- Statistics Cards:
EpisodeStatsCard,PollStatsCard - Analytics:
GoogleAnalyticsKPI,SocialMediaStats,ChartRow,MetricsReferrals
Beautiful loading states for better UX:
- All dashboard components have corresponding shimmer loaders
- Table shimmer loaders for episodes and polls
- Poll details page shimmer
Global toast notification system:
- Success, error, warning, and info variants
- Auto-dismiss with configurable duration
- Accessible via
useToast()hook
id(UUID, Primary Key)title(TEXT, Required)description(TEXT)episode_number(INTEGER, Required)season_number(INTEGER, Required)unique_episode_id(TEXT, Unique, Required)visibility(AVAILABLE, UPCOMING, LOCKED, DRAFT, ARCHIVED)access_level(free, premium, vip)status(DRAFT, PUBLISHED)- Media URLs, tags, genres, and more
id(UUID, Primary Key)episode_id(UUID, Foreign Key to episodes)title(TEXT, Required)description(TEXT)status(DRAFT, LIVE, ENDED, ARCHIVED)duration_days(INTEGER)starts_at,ends_at(TIMESTAMPTZ)
id(UUID, Primary Key)poll_id(UUID, Foreign Key to polls)name(TEXT, Required)description(TEXT)vote_count(INTEGER)display_order(INTEGER)
npm run dev- Start development server with Prettier formattingnpm run build- Build for production with Prettier formattingnpm start- Start production servernpm run lint- Run ESLintnpm run format- Format code with Prettiernpm run format:check- Check code formattingnpm run check:deployment- Check project readiness for Vercel deployment
- Setup: Configure environment variables and database
- Development: Make changes with hot reload enabled
- Testing: Test CRUD operations via UI or API
- Build: Verify production build works correctly
- Deploy: Deploy to your hosting platform
# Required
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your_anon_key
# Required for authentication
NEXT_PUBLIC_STATIC_ADMIN_EMAIL=admin@example.com
NEXT_PUBLIC_STATIC_ADMIN_PASSWORD=secure_password
# Optional (for scripts)
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key- API Documentation: See
doc/API_DOCUMENTATION.md - Supabase Setup: See
doc/SUPABASE_SETUP.md(if available) - Database Schema: See
supabase/migrations/create_tables.sql - Vercel Deployment Guide: See
doc/VERCEL_DEPLOYMENT_NOT_FOUND_GUIDE.md(troubleshooting deployment errors)
- 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
MIT