Skip to main content

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-bombs bucket)
  • ✅ Video bomb records stored in video_bombs database table
  • ✅ Public URLs route to /vb/:publicUrl landing 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 RPC record_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-bombs bucket is public and getPublicUrl issues 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.title is 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 VideoBlasts
  • VideoBlasts:create - Create VideoBlasts
  • VideoBlasts:update - Edit VideoBlasts
  • VideoBlasts: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 status
  • isPaused - Pause status
  • recordedVideo - Recorded video blob URL
  • uploadedVideo - Uploaded video file
  • showCreateDialog - Dialog visibility
  • VideoBlastTitle - Form title
  • VideoBlastEntity - Selected organization
  • isDragging - Drag-and-drop state
  • videoRef - Video element reference
  • mediaRecorderRef - MediaRecorder reference
  • streamRef - MediaStream reference

Global State (AppContext)

  • VideoBlasts - Array of VideoBlasts
  • addVideoBlast - Function to add
  • deleteVideoBlast - Function to delete

Dependencies

Internal Dependencies

  • AppContext - Global state
  • UI components (Card, Button, Dialog, Input, etc.)

External Libraries

  • lucide-react - Icons
  • sonner - 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 - VideoBlasts array (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

Ready to get started?Start Plus Trial