Subscription Gate Modal Implementation
Date: January 9, 2026 Status: ✅ COMPLETE
Overview
Implemented a comprehensive subscription gate system that displays a glassmorphic modal when users without proper subscriptions attempt to access premium content. Admin users bypass all subscription requirements.
Backend Changes
1. Content Stream Endpoint
File: /backend/app/api/routes/content.py (lines 195-208)
# Admin users bypass subscription checks
is_admin = current_user.role in ["super_admin", "admin"]
# Check subscription (skip for admins)
if not is_admin:
required_tier = content.requires_subscription
user_tier = current_user.subscription_tier
tier_levels = {"basic": 1, "premium": 2, "family": 3}
if not user_tier or tier_levels.get(user_tier, 0) < tier_levels.get(required_tier, 1):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Subscription upgrade required",
)Features:
- Checks if user has admin role (super_admin or admin)
- Admins bypass subscription checks entirely
- Regular users must have appropriate subscription tier
- Returns 403 Forbidden with clear message when subscription is required
2. Live Channel Stream Endpoint
File: /backend/app/api/routes/live.py (lines 130-139)
# Admin users bypass subscription checks
is_admin = current_user.role in ["super_admin", "admin"]
# Check subscription for live TV (skip for admins)
if not is_admin:
if not current_user.subscription_tier or current_user.subscription_tier == "basic":
raise HTTPException(
status_code=403,
detail="Live TV requires Premium or Family subscription",
)Features:
- Same admin bypass logic as VOD content
- Live TV requires Premium or Family subscription
- Returns 403 error for unauthorized users
Frontend Implementation
1. SubscriptionGateModal Component
File: /tv-app/src/components/player/SubscriptionGateModal.tsx
Features:
- Glassmorphic Design: Uses
LinearGradientbackgrounds matching app aesthetic - RTL Support: Full right-to-left text support for Hebrew
- Header Section: Warning icon with "Subscription Required" title
- Content Info: Shows which content requires subscription
- Tier Card: Displays premium tier features with checkmarks
- Info Box: Explains subscription benefits
- Action Buttons: Cancel (dismiss) and Upgrade Now buttons
- Modal Styling:
- Dark semi-transparent backdrop (rgba(0, 0, 0, 0.7))
- Glass background with gradient (rgba(26, 26, 46, 0.95) to rgba(20, 20, 35, 0.95))
- Border: 1px glassBorder color
- Header accent bar with warning color
Props:
export interface SubscriptionGateModalProps {
visible: boolean;
onClose: () => void;
onUpgrade: () => void;
requiredTier?: 'basic' | 'premium' | 'family';
contentTitle?: string;
contentType?: 'vod' | 'live' | 'radio' | 'podcast';
}2. PlayerScreen Integration
File: /tv-app/src/screens/PlayerScreen.tsx
Changes:
Added import:
SubscriptionGateModalfrom player componentsAdded state variables:
showSubscriptionGate: boolean for modal visibilitysubscriptionRequired: stores required tier level
Updated
loadStream()function:- Resets subscription gate state at start
- Catches 403 errors and shows modal instead of generic error
- Checks for subscription error in both formats:
err.status === 403err.response?.status === 403
Added handler:
handleSubscriptionUpgrade()- Closes modal
- Navigates to Subscribe screen
Rendered modal in JSX:
tsx<SubscriptionGateModal visible={showSubscriptionGate} onClose={() => setShowSubscriptionGate(false)} onUpgrade={handleSubscriptionUpgrade} requiredTier={subscriptionRequired} contentTitle={title} contentType={type} />
3. Component Exports
File: /tv-app/src/components/player/index.ts
Added exports:
export { SubscriptionGateModal } from './SubscriptionGateModal';
export type { SubscriptionGateModalProps } from './SubscriptionGateModal';Internationalization (i18n)
English Translations
File: /shared/i18n/locales/en.json
Added under player section:
"subscription": {
"requiredTitle": "Subscription Required",
"requiredMessage": "requires a paid subscription",
"upgradeInfo": "Upgrade your subscription to access premium content",
"upgrade": "Upgrade Now"
}Hebrew Translations
File: /shared/i18n/locales/he.json
Added under player section:
"subscription": {
"requiredTitle": "נדרשת הנתקה",
"requiredMessage": "דורש מנוי בתשלום",
"upgradeInfo": "שדרג את המנוי שלך כדי לגשת לתוכן פרימיום",
"upgrade": "שדרג כעת"
}User Experience Flow
For Regular Users (No Subscription)
- User attempts to play premium content
- Backend returns 403 Forbidden
- PlayerScreen catches error
- SubscriptionGateModal appears with:
- Content title
- Subscription requirement message
- Premium tier features list
- "Upgrade Now" button
- User can:
- Tap "Upgrade Now" → Navigate to subscription page
- Tap "Cancel" → Dismiss modal and return to previous screen
For Admin Users
- Admin attempts to play any content
- Backend checks
current_user.roleand finds "admin" or "super_admin" - Subscription check is skipped
- Stream URL is returned directly
- Content plays normally without subscription gate
Subscription Tiers
Tier Levels
- Basic: Level 1 - Limited access
- Premium: Level 2 - Full access to most content
- Family: Level 3 - Premium features + multi-device + family profiles
Live TV Requirements
- Requires: Premium or Family
- Blocked for: Basic or no subscription
VOD Content Requirements
- Customizable per content item via
requires_subscriptionfield - Compared using tier levels
Error Handling
Subscription Error Detection
Catches 403 Forbidden responses from:
- Content stream endpoint:
/content/{id}/stream - Live channel stream endpoint:
/live/{channel_id}/stream
Error Response Checks
if (err && typeof err === 'object' && 'status' in err && err.status === 403) {
setShowSubscriptionGate(true);
} else if (err && typeof err === 'object' && 'response' in err && err.response?.status === 403) {
setShowSubscriptionGate(true);
}Technical Details
Styling System
Colors Used:
- Warning:
colors.warning(yellow/orange) - Success:
colors.success(green) - Primary:
colors.primary(cyan/blue) - Glass:
colors.glass,colors.glassBorder - Text Secondary:
colors.textSecondary
- Warning:
Spacing:
- Padding: lg (24px), md (16px), sm (8px), xs (4px)
- Border Radius: lg, md, sm
Typography:
- Header: fontSize.lg, fontWeight 600
- Content: fontSize.sm
- Tier Name: fontSize.md, fontWeight 600
RTL Handling
- Text alignment:
textAlign: 'right'for Hebrew - Flex direction:
flex-direction: 'row-reverse'for button layout - Border positioning: Left to Right for English, Right to Left for Hebrew
- All text uses
isRTLstate fromuseDirection()hook
API Integration
Stream URL Endpoints
GET /content/{content_id}/stream
- Requires authentication
- Admin bypass: ✅
- Returns:
url: Stream URLtype: Stream type (hls, dash)is_drm_protected: DRM statusdrm_key_id: (if DRM protected)
GET /live/{channel_id}/stream
- Requires authentication
- Admin bypass: ✅
- Returns:
url: Stream URLtype: Stream typeis_drm_protected: DRM status
Testing Checklist
Backend
- [ ] Admin user can stream premium content without error
- [ ] Regular user with no subscription gets 403 error
- [ ] Regular user with basic subscription gets 403 for live TV
- [ ] Regular user with premium subscription can stream live TV
- [ ] Content-specific subscription requirements are enforced
- [ ] Subscription tier levels are correctly compared
Frontend
- [ ] Modal appears when 403 error is caught
- [ ] Modal displays correct content title
- [ ] "Upgrade Now" button navigates to Subscribe screen
- [ ] "Cancel" button closes modal
- [ ] Modal displays in correct language (English/Hebrew)
- [ ] RTL layout works correctly in Hebrew
- [ ] Glassmorphic styling matches app aesthetic
- [ ] Features list displays with checkmarks
User Experience
- [ ] Error message is clear and actionable
- [ ] Subscription requirements are clearly explained
- [ ] User can easily dismiss modal
- [ ] User can easily navigate to upgrade
- [ ] Modal doesn't interfere with other player controls
Files Modified/Created
Created Files
/tv-app/src/components/player/SubscriptionGateModal.tsx(270+ lines)
Modified Files
/backend/app/api/routes/content.py- Added admin bypass to subscription check/backend/app/api/routes/live.py- Added admin bypass to subscription check/tv-app/src/screens/PlayerScreen.tsx- Integrated modal and error handling/tv-app/src/components/player/index.ts- Added modal exports/shared/i18n/locales/en.json- Added English translations/shared/i18n/locales/he.json- Added Hebrew translations
Key Features
✅ Admin Bypass: Admins can access any content without subscription ✅ Glassmorphic Design: Modal matches existing app aesthetic ✅ RTL Support: Full Hebrew language support with proper text direction ✅ Clear UX: Users understand what's required and how to upgrade ✅ Error Handling: Distinguishes subscription errors from other errors ✅ Internationalization: English and Hebrew translations included ✅ Tier Information: Shows users what each subscription tier includes ✅ Navigation: Easy access to subscription upgrade page
Next Steps (Optional Enhancements)
- [ ] Add more subscription tier details to modal
- [ ] Show current user's subscription status in modal
- [ ] Display pricing information
- [ ] Add comparison table of tiers
- [ ] Track failed access attempts for analytics
- [ ] Send notification to admin of upgrade attempts
- [ ] Add promotional offers for upgrading
- [ ] Implement trial period logic
Summary
The subscription gate feature is now fully implemented with:
- Backend: Admin bypass + subscription validation
- Frontend: Glassmorphic modal with full error handling
- UX: Clear messaging and easy navigation to upgrade
- i18n: Full English and Hebrew support with RTL
- Design: Consistent with existing app aesthetic
The system allows admins full access while protecting premium content for regular users.