VideoBlast Manager
VideoBlast Manager
Component File: src/features/fundraising/components/VideoBlastManager.tsx Landing Page: src/features/fundraising/components/VideoBlastLandingPage.tsx Route / navigation: /fundraising, fundraisingTool = video-blast. See 00-FUNDRAISING-HUB.md. Public Route: /vb/:publicUrl (no auth required) Embed Route: /vb/:publicUrl/embed (no auth required) Access Level: Parent Org and Fund Users with Fundraising access (position-based)
Overview
The VideoBlast Manager enables users to create video-centric donation landing pages. Users can record videos directly using their webcam or upload pre-recorded videos. Each VideoBlast page is a personalized donation landing page featuring the video prominently, designed to increase donor engagement through personal storytelling. This tool is particularly effective for peer-to-peer fundraising and campaign launches.
Implementation Status: ✅ COMPLETE
Backend Integration
- ✅ Videos stored in Supabase Storage (
video-bombsbucket) - ✅ Video bomb records stored in
video_bombsdatabase table - ✅ Public URLs route to
/vb/:publicUrllanding pages - ✅ Stripe checkout integration for donations
- ✅ View tracking on landing page visits (deduped per-tab via
sessionStorage; embed route does not increment) - ✅ Donation attribution: checkout metadata
video_blast_id→ Stripe webhook → atomic SECURITY DEFINER RPCrecord_video_blast_donation. The earlier read-modify-write attribution path was replaced (Apr 21 2026) because concurrent donations on a viral share lost counts. - ✅ RLS hardening: anon can read active blasts for shared pages; authenticated users remain org-scoped
Known Limitations
- Storage objects remain publicly accessible after `status='inactive'` or row deletion: the
video-bombsbucket is public andgetPublicUrlissues stable URLs. RLS only protects the table row; anyone who already has the file URL can still play it. Moving to private bucket + signed URLs is tracked separately because it touches journeys, donor-page embeds, and email link rewrites. - Bot link previews (Slack / Twitter / iMessage) are not populated: the landing page is rendered by the SPA, so crawlers that don't execute JavaScript see only the shell HTML.
document.titleis set at runtime for the browser tab, but proper Open Graph / Twitter Card support requires prerendering or a UA-aware edge function. Tracked separately.
Storage Limits
- Max video duration: 2 minutes (120 seconds)
- Max file size: 50MB
- Supabase Storage quota: 100GB (Pro plan)
- Estimated capacity: ~2,500-5,000 short videos
UI Features
Main Features
- Video Recording:
- Record button to start webcam recording
- Live preview during recording
- Recording timer with 2-minute countdown
- Auto-stop at 2 minute limit
- Pause/Resume controls
- Stop recording button
- Re-record option
- Video Upload:
- Drag-and-drop file upload
- File browser upload
- Supported formats: MP4, WebM, MOV
- 2-minute duration validation
- 50MB file size limit
- VideoBlast Creation Dialog:
- Title input
- Organization selector
- Video preview
- Create button with upload progress
- VideoBlast List:
- Thumbnail preview
- Title and organization
- Created date
- View count
- Donation count and total raised
- Copy link button
- Delete button
- Back to Marketing Hub button
Recording Interface
┌─────────────────────────────────────────┐
│ Create VideoBlast │
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ │
│ │ [0:45/2:00]│ │
│ │ [Live Video Preview] │ │
│ │ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ [🔴 Record] [⏸️ Pause] [⏹️ Stop] │
│ │
│ OR │
│ │
│ [📤 Upload Video] │
│ Drag & drop or click to browse │
│ Supported: MP4, WebM, MOV (max 2 min) │
│ │
└─────────────────────────────────────────┘Create VideoBlast Dialog
┌─────────────────────────────────────────┐
│ Create VideoBlast Page │
├─────────────────────────────────────────┤
│ │
│ Title * │
│ [My Fundraising Story ] │
│ │
│ Organization * │
│ [Awakenings ▼] │
│ │
│ Video Preview │
│ ┌─────────────────────────────────┐ │
│ │ [Video Thumbnail/Preview] │ │
│ └─────────────────────────────────┘ │
│ │
│ [Cancel] [Create VideoBlast]│
└─────────────────────────────────────────┘VideoBlast List
My VideoBlasts
┌────────────────────┐ ┌────────────────────┐
│ [Video Thumbnail] │ │ [Video Thumbnail] │
│ │ │ │
│ My Story │ │ Campaign Launch │
│ Awakenings │ │ Bloom Strong │
│ Created: 10/15/25 │ │ Created: 10/18/25 │
│ │ │ │
│ [🔗 Copy Link] │ │ [🔗 Copy Link] │
│ [🗑️ Delete] │ │ [🗑️ Delete] │
└────────────────────┘ └────────────────────┘Data Requirements
VideoBlast
- id (uuid) - Unique identifier
- organization_id (uuid) - Organization
- title (string) - VideoBlast title
- video_url (string) - Video file URL
- thumbnail_url (string) - Video thumbnail
- public_url (string) - Public landing page URL
- created_by (uuid) - Creator user ID
- created_at (timestamp) - Creation date
- views (integer) - Page view count
- donations_count (integer) - Donations from this page
- donations_total (decimal) - Total raised
- status (enum) - 'active', 'inactive'
Video Upload
- file (binary) - Video file
- filename (string) - Original filename
- file_size (integer) - Size in bytes
- mime_type (string) - Video MIME type
- duration (integer) - Video duration in seconds
Database Functions
VideoBlast operations are implemented in src/lib/db/video-bombs.ts (and re-exported from src/lib/db.ts):
fetchVideoBlasts(entityId)
Fetches all video bombs for an organization.
fetchVideoBlastPublic(slug)
Fetches a single public video blast + org name via SECURITY DEFINER RPC (get_video_blast_public).
createVideoBlast({ entityId, title, videoUrl, createdBy })
Creates a new video bomb record with auto-generated public URL slug.
deleteVideoBlast(id)
Deletes a video bomb record from the database.
uploadVideoBlastVideo(file, organizationId)
Uploads video file to Supabase Storage video-bombs bucket.
deleteVideoBlastVideo(videoUrl)
Deletes video file from Supabase Storage.
incrementVideoBlastViews(id)
Increments view count via RPC (increment_video_bomb_views). No direct table write fallback. Caller is responsible for dedup; VideoBlastLandingPage uses sessionStorage to count once per tab session per slug.
Donation attribution (server-side only)
There is no browser wrapper for donation attribution. The previous recordVideoBlastDonation client function was removed (Apr 21 2026) because read-modify-write from the browser both lost concurrent updates and bypassed payment-as-source-of-truth. All counter writes happen in the Stripe webhook via supabase.rpc('record_video_blast_donation', { p_video_blast_id, p_organization_id, p_amount }) — see supabase/functions/stripe-webhook/index.ts.
Supabase Storage
Bucket Configuration
- Bucket name:
video-bombs - Public: Yes (for video playback on landing pages)
- File size limit: 50MB
- Allowed MIME types: video/mp4, video/webm, video/quicktime, image/jpeg, image/png, image/webp
RLS Policies
- Authenticated users can upload videos
- Public (anon) can view active rows for shared landing pages
- Authenticated reads/writes remain org-scoped
- Authenticated users can delete their own videos
Runtime
> Runtime: Use Supabase clients, database RPC, and edge functions (and Stripe for payments where applicable).
Request/Response Schemas
interface VideoBlast {
id: string;
organization_id: string;
organization_name: string;
title: string;
video_url: string;
thumbnail_url: string;
public_url: string;
created_by: string;
created_by_name: string;
created_at: string;
views: number;
donations_count: number;
donations_total: number;
status: 'active' | 'inactive';
}
interface VideoBlastFormData {
title: string;
organization_id: string;
video_url: string;
thumbnail_url: string;
}Authentication & Authorization
Required Permissions
VideoBlasts:read- View VideoBlastsVideoBlasts:create- Create VideoBlastsVideoBlasts:update- Edit VideoBlastsVideoBlasts:delete- Delete VideoBlasts
Role-Based Access
- Parent Org (`parent_org`): View VideoBlasts across all nonprofits (subject to position/access level)
- Fund User (`fund_user`): Create and manage their nonprofit's VideoBlasts (subject to position/access level)
- Read-only users: Can view/manage links + analytics, but cannot record/upload/create/delete
- Positions: Directors and assistants typically have Marketing access; custom positions must enable Marketing permissions
- Donor/Volunteer: No access (can view public pages)
Business Logic & Validations
Frontend Validations
- Title required (max 100 characters)
- Organization required
- Video required (either recorded or uploaded)
- File size limit: 50MB
- Supported formats: MP4, WebM, MOV
- Camera permissions check
Backend Validations (Supabase)
- Valid organization access
- Video file validation
- File size limit enforcement
- URL uniqueness for public_url
Business Rules
- Each VideoBlast has unique public URL
- Videos stored in cloud storage (S3, CloudFlare, etc.)
- Thumbnails auto-generated from video
- Public pages are SEO-optimized
- Analytics tracked automatically
- Videos transcoded for web optimization
- Donation button integrated on public page
State Management
Local State
isRecording- Recording statusisPaused- Pause statusrecordedVideo- Recorded video blob URLuploadedVideo- Uploaded video fileshowCreateDialog- Dialog visibilityVideoBlastTitle- Form titleVideoBlastEntity- Selected organizationisDragging- Drag-and-drop statevideoRef- Video element referencemediaRecorderRef- MediaRecorder referencestreamRef- MediaStream reference
Global State (AppContext)
VideoBlasts- Array of VideoBlastsaddVideoBlast- Function to adddeleteVideoBlast- Function to delete
Dependencies
Internal Dependencies
AppContext- Global state- UI components (Card, Button, Dialog, Input, etc.)
External Libraries
lucide-react- Iconssonner- Toast notifications- Browser MediaRecorder API - Video recording
- Browser MediaDevices API - Camera access
Error Handling
Error Scenarios
1. Camera Access Denied: Show toast "Camera access denied. Please upload a video instead." 2. No Camera Found: Show toast "No camera found. Please upload a video instead." 3. File Too Large: Show error "File exceeds 50MB limit" 4. Invalid Format: Show error "Unsupported video format" 5. Upload Failed: Show toast "Failed to upload video" 6. Create Failed: Show toast "Failed to create VideoBlast" 7. Permission Error: Show toast "You don't have permission"
Loading States
- Recording: Live preview with recording indicator
- Upload: Progress bar during upload
- Processing: Processing indicator after upload
- Create: Button loading state
Mock Data to Remove
AppContext.tsx-VideoBlastsarray (move to API)VideoBlastManager.tsx- Local state management (use API)- Move interfaces to
src/types/VideoBlasts.ts
Migration Notes
Phase 1: Video Upload
1. Integrate with cloud storage (S3, CloudFlare R2) 2. Implement video upload endpoint 3. Add thumbnail generation 4. Test file validation
Phase 2: VideoBlast Creation
1. Implement CRUD endpoints 2. Generate unique public URLs 3. Create public landing page template 4. Test donation integration
Phase 3: Analytics
1. Implement view tracking 2. Track donation attribution 3. Add analytics dashboard 4. Generate reports
Phase 4: Optimization
1. Video transcoding for web 2. Adaptive bitrate streaming 3. CDN integration 4. Performance optimization
Related Documentation
Additional Notes
Public Landing Page Features
- Video player (autoplay on mobile)
- Compelling headline
- Donation form
- Progress bar (if campaign goal set)
- Social sharing buttons
- Creator information
- Organization branding
Video Recording Best Practices
- Good lighting
- Clear audio
- 1-3 minutes optimal length
- Personal storytelling
- Clear call-to-action
- Test before recording
Use Cases
1. Peer-to-Peer Fundraising: Supporters create personal appeals 2. Campaign Launches: Announce new initiatives 3. Impact Stories: Share beneficiary testimonials 4. Event Promotion: Promote fundraising events 5. Thank You Videos: Donor appreciation
Technical Specifications
Supported Formats:
- MP4 (H.264 codec)
- WebM (VP8/VP9 codec)
- MOV (QuickTime)
Recommended Settings:
- Resolution: 1080p or 720p
- Frame rate: 30fps
- Bitrate: 5-10 Mbps
- Audio: AAC, 128kbps
Browser Compatibility:
- Chrome/Edge: Full support
- Firefox: Full support
- Safari: Full support (with permissions)
- Mobile: Upload only (recording limited)
Integration with Donations
- Public page includes donation form
- Donations attributed to VideoBlast
- Creator notified of donations
- Analytics track conversion rate
- Social proof (recent donations shown)
SEO Optimization
- Meta tags for social sharing
- Open Graph tags
- Twitter Card tags
- Schema.org markup
- Optimized page load speed
Synced from IFMmvp-Frontend documentation: pages/fundraising/03-VIDEOBLAST-MANAGER.md
Ready to Get Started?
See how Alignmint can simplify your nonprofit's operations. Schedule a free demo with our team and we'll walk you through everything.
Questions? Email us at steven@getalignmint.org