EduCast: Educational Podcast Platform
Project Overview
EduCast is an educational podcast platform MVP designed as a learning project to explore full-stack development with React, Express, and Supabase. The platform allows professors to share educational content via YouTube video embeddings, while students can discover and engage with educational material through a modern web interface.
Built during a development sprint, EduCast demonstrates practical implementation of Supabase authentication, database queries with Drizzle ORM, and responsive UI design with shadcn/ui components. While the initial scope included extensive media upload capabilities, the final implementation focuses on YouTube video embeddings as the primary content delivery method.
Key Features
Authentication & User Management
- Supabase-powered authentication with email/password
- Role-based access control (Student, Professor, Admin, Super Admin)
- User profile management with avatars
- Protected routes based on user roles
Content Management
- YouTube video embedding for educational content
- Podcast metadata management (title, description, thumbnails)
- Professor dashboard for content oversight
- Content categorization and organization
Student Experience
- Browse embedded YouTube educational videos
- Personal library with saved content
- Comment system for engagement
- Search and discovery features
Admin Features
- User management dashboard
- Platform analytics and statistics
- Content moderation capabilities
Tech Stack
Frontend
| Technology | Purpose |
|---|---|
| React 18.3 | UI library with hooks |
| TypeScript 5.6 | Type-safe development |
| Vite 5.4 | Build tool and dev server |
| Wouter 3.3 | Client-side routing |
| Tailwind CSS 3.4 | Utility-first styling |
| shadcn/ui | Component library (Radix UI) |
| TanStack Query 5.60 | Server state management |
| React Hook Form 7.55 | Form handling |
| Zod 3.24 | Schema validation |
| Lucide React | Icon library |
| React Player 2.16 | YouTube embed player |
Backend
| Technology | Purpose |
|---|---|
| Express 4.21 | Node.js web framework |
| Drizzle ORM 0.39 | Database queries |
| PostgreSQL | Database via Supabase |
| Supabase 2.50 | Authentication and database hosting |
Unused Dependencies
The project includes several packages that were installed but not utilized in the final implementation:
- Passport.js (replaced by Supabase Auth)
- Multer (file uploads not implemented)
- Express Session (session management via Supabase)
- WebSockets (real-time features not implemented)
Architecture & Design
Authentication with Supabase
The platform uses Supabase Authentication instead of the initially planned Passport.js implementation. Supabase handles:
- User registration and login
- JWT token management
- Session persistence
- Email verification
- Password reset flows
All authentication logic is managed through Supabase client SDK calls, eliminating the need for custom Passport.js strategies.
Database Queries
Instead of complex API route handlers, the application performs direct database queries using Drizzle ORM. This approach simplifies:
- Data fetching with TanStack Query
- CRUD operations for podcasts and users
- Real-time data synchronization with Supabase
YouTube Embedding Approach
Rather than implementing file upload infrastructure, podcasts are stored as YouTube video URLs. This approach:
- Eliminates storage and bandwidth costs
- Leverages YouTube's video player and CDN
- Simplifies content management
- Uses unlisted YouTube videos for privacy
Trade-offs:
- Dependency on YouTube's availability
- Limited control over playback experience
- Requires professors to upload to YouTube first
- No offline access capabilities
Database Schema
Users (via Supabase Auth)
Managed by Supabase's auth.users table with custom metadata:
- id (UUID)
- role (stored in user_metadata)
- created_at
Podcasts Table
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| title | TEXT | Podcast title |
| description | TEXT | Content description |
| youtubeUrl | TEXT | YouTube video URL |
| thumbnailUrl | TEXT | Thumbnail image URL |
| professorId | UUID | Foreign key to Supabase auth.users |
| createdAt | TIMESTAMP | Creation timestamp |
| updatedAt | TIMESTAMP | Last modified timestamp |
Comments Table
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| content | TEXT | Comment text |
| userId | UUID | Foreign key to auth.users |
| podcastId | UUID | Foreign key to podcasts |
| createdAt | TIMESTAMP | Creation timestamp |
Playlists and Views
Additional tables for user playlists and view tracking follow similar simple schemas with foreign key relationships to users and podcasts.
Setup & Installation
Prerequisites
- Node.js 18+
- Supabase account (free tier works)
- npm or yarn
Quick Start
Clone repository
- git clone https://github.com/shinaylim/educast.git
- cd educast
Install dependencies
- npm install
Configure Supabase
- Create .env file with:
- SUPABASE_URL=your_supabase_url
- SUPABASE_KEY=your_supabase_anon_key
Run database migrations
- npm run db:push
Start development server
- npm run dev
Application runs at http://localhost:5000
Supabase Setup
- Create a new Supabase project at supabase.com
- Copy your project URL and anon key
- Add to
.envfile:
SUPABASE_URL=https://your-project.supabase.co SUPABASE_KEY=your-anon-key
- Database tables are created via Drizzle migrations
Implementation Details
Authentication Flow
- User enters credentials in login form
- Supabase client SDK sends auth request
- Supabase returns JWT token and user object
- Token stored in localStorage and httpOnly cookie
- Protected routes check token validity
- React Context provides auth state globally
YouTube Video Embedding
Professors add content by:
- Uploading video to YouTube (unlisted)
- Copying the YouTube URL
- Submitting URL via professor dashboard
- System stores URL in database
- React Player component renders embed
Limitations & Technical Debt
Known Issues
- Unused Dependencies: Many packages installed but not implemented (Passport.js, Multer, WebSockets)
- API Routes: Several defined routes aren't actually used; most queries happen client-side
- YouTube Dependency: Platform breaks if YouTube is unavailable
- No File Uploads: Initial media upload system never completed
- Session Management: Mix of Supabase auth and unused Express session middleware
- Code Organization: Some components and routes are duplicated or unused
Why YouTube Embeddings?
The decision to use YouTube embeddings instead of file uploads:
- Faster MVP development - No need for storage infrastructure
- Reduced hosting costs - YouTube handles video delivery
- Simpler implementation - React Player handles playback
- Learning focus - Project prioritized auth and database over media handling
This approach is not production-ready but suitable for:
- Learning projects and portfolios
- Low-budget MVPs
- Internal educational tools
- Proof-of-concept demonstrations
Development Workflow
Available Scripts
| Script | Purpose |
|---|---|
| npm run dev | Start dev server |
| npm run build | Build for production |
| npm run db:push | Push schema to database |
Code Organization
- Components organized by role (professor, student, admin)
- Supabase client initialized in
lib/supabase.ts - Auth state managed via React Context in
hooks/use-auth.tsx - Database queries co-located with components using TanStack Query
Deployment
Render/Vercel Deployment
- Connect GitHub repository
- Set environment variables:
- SUPABASE_URL
- SUPABASE_KEY
- Build command:
npm run build - Start command:
npm start
Supabase Configuration
- Enable authentication in Supabase dashboard
- Configure email templates for auth flows
- Set up Row Level Security (RLS) policies if needed
- Add allowed domains for CORS
Future Improvements
To make this production-ready:
- Clean up dependencies - Remove unused packages
- Implement proper file uploads - Add Supabase Storage integration
- Consolidate API routes - Remove unused endpoints
- Add error boundaries - Better error handling throughout
- Implement testing - Unit and integration tests
- Optimize queries - Add proper indexing and caching
- Add video transcoding - Move away from YouTube dependency
- Improve state management - Consolidate auth/data patterns
Lessons Learned
This project demonstrates common challenges in MVP development:
- Scope creep: Started with ambitious features, scaled back to YouTube embeds
- Dependency management: Over-installing packages before knowing requirements
- Architecture decisions: Mixing approaches (Passport.js + Supabase) causes confusion
- Time constraints: Some features planned but never implemented
The result is a functional but messy codebase that works for its intended purpose: demonstrating full-stack development skills while delivering a working educational platform prototype.
Conclusion
EduCast represents a realistic learning project with both successes and technical debt. The Supabase authentication works well, the UI is polished with shadcn/ui, and the core functionality delivers value. However, the YouTube embedding approach and unused dependencies highlight areas for improvement in future iterations.
For portfolio purposes, this project demonstrates practical skills in React, TypeScript, Supabase integration, and full-stack architecture, while honestly acknowledging its limitations and trade-offs made during development.