19 KiB
Product Requirements Document (PRD)
SelfieCam - Professional Selfie Camera App
Version: 1.0
Platform: iOS 18.0+
Language: Swift 6 with strict concurrency
Framework: SwiftUI
Executive Summary
SelfieCam is a professional-grade selfie camera app featuring a customizable screen-based ring light overlay, premium camera controls, and beautiful branding. The app targets content creators, makeup artists, video call professionals, and anyone who needs flattering lighting for selfies.
Target Audience
- Content creators and influencers
- Makeup artists and beauty professionals
- Video call and streaming professionals
- Casual users seeking better selfie lighting
- Portrait photographers needing on-the-go lighting
Technical Requirements
Platform & Tools
| Requirement | Specification |
|---|---|
| iOS Deployment Target | iOS 18.0+ |
| Swift Version | Swift 6 with strict concurrency checking |
| UI Framework | SwiftUI (primary) |
| Persistence | iCloud via CloudSyncManager |
| Subscriptions | RevenueCat SDK |
| Camera | MijickCamera framework |
| Design System | Bedrock (local package) |
Architecture Principles
- Protocol-Oriented Programming (POP) - All shared capabilities defined via protocols before concrete types
- MVVM-lite - Views are "dumb" renderers; all logic lives in
@Observableview models - Bedrock Design System - Centralized design tokens, no magic numbers
- Settings layout contract:
SettingsCardowns horizontal insets, custom rows useSettingsCardRow, and in-card separators useSettingsDivider
- Settings layout contract:
- Full Accessibility - Dynamic Type, VoiceOver labels/hints/traits/announcements
- Modern Swift & SwiftUI - Swift 6 concurrency,
@MainActor, modern APIs - Testable & Reusable Design - Protocols enable mocking and future package extraction
Feature Requirements
FR-100: Core Camera System
FR-101: Camera Preview
- Priority: P0 (Critical)
- Description: Full-screen camera preview with real-time display
- Acceptance Criteria:
- Smooth, low-latency camera preview
- Supports both front and back camera
- Camera switching via UI button
- Prevents screen dimming during camera use
- Uses MijickCamera framework for SwiftUI-native handling
FR-102: Photo Capture
- Priority: P0 (Critical)
- Description: High-quality photo capture with multiple trigger methods
- Acceptance Criteria:
- Capture button triggers photo capture
- Volume buttons trigger capture (hardware shutter)
- Camera Control button full press triggers capture (iPhone 16+)
- Post-capture preview with share functionality
- Auto-save option to Photo Library
FR-103: Zoom Control
- Priority: P1 (High)
- Description: Pinch-to-zoom gesture support
- Acceptance Criteria:
- Smooth pinch-to-zoom interpolation
- Zoom level persists during session
- Zoom resets on camera switch (optional behavior)
FR-104: Camera Control Button Support
- Priority: P2 (Medium)
- Description: iPhone 16+ Camera Control button integration
- Acceptance Criteria:
- Full press triggers photo capture
- Light press locks focus/exposure (if API available)
- Uses
AVCaptureEventInteraction(iOS 17.2+)
- Known Limitations:
- Light press may be restricted to first-party apps
- Swipe-to-zoom is Apple-exclusive API
FR-200: Ring Light System
FR-201: Ring Light Overlay
- Priority: P0 (Critical)
- Description: Screen-based ring light effect using colored border
- Acceptance Criteria:
- Configurable border thickness (10-120pt range)
- Border renders around camera preview
- Quick enable/disable toggle
- Smooth transition animations
FR-202: Ring Light Colors
- Priority: P0 (Critical)
- Description: Multiple color temperature presets
- Free Colors:
- Pure White
- Warm Cream
- Premium Colors:
- Ice Blue
- Soft Pink
- Warm Amber
- Cool Lavender
- Acceptance Criteria:
- Color picker UI with visual swatches
- Premium colors show lock indicator for free users
- Premium users can access custom color picker
FR-203: Ring Light Brightness
- Priority: P1 (High)
- Description: Adjustable ring light opacity/brightness
- Acceptance Criteria:
- Slider control for brightness (10%-100%)
- Real-time preview of brightness changes
- Debounced saving (300ms) to prevent excessive iCloud writes
FR-300: Flash System
FR-301: Flash Modes
- Priority: P1 (High)
- Description: Multiple flash options for photo capture
- Modes:
- Off
- On
- Auto
- Acceptance Criteria:
- Mode selector in camera UI
- Flash fires during capture when enabled
- Auto mode uses ambient light detection
FR-302: Front Flash
- Priority: P1 (High)
- Description: Screen brightness-based flash for front camera
- Acceptance Criteria:
- Screen brightness increases to maximum during front camera capture
- Returns to original brightness after capture
FR-303: Flash Sync (Premium)
- Priority: P2 (Medium)
- Description: Match flash color with ring light color
- Acceptance Criteria:
- Premium feature with appropriate gating
- Screen color matches current ring light color during flash
- Toggle in settings to enable/disable
FR-400: Self-Timer System
FR-401: Timer Options
- Priority: P1 (High)
- Description: Countdown timer before photo capture
- Free Options:
- Off
- 3 seconds
- Premium Options:
- 5 seconds
- 10 seconds
- Acceptance Criteria:
- Visual countdown indicator
- Audio feedback (optional)
- Cancel option during countdown
- VoiceOver announces countdown
FR-500: Display & Enhancement Features
FR-501: Grid Overlay
- Priority: P2 (Medium)
- Description: Rule-of-thirds composition guide
- Acceptance Criteria:
- Toggle in settings to show/hide
- Semi-transparent grid lines
- Does not interfere with tap gestures
FR-502: True Mirror Mode (Premium)
- Priority: P2 (Medium)
- Description: Horizontally flipped preview like a real mirror
- Acceptance Criteria:
- Premium feature with appropriate gating
- Live preview is mirrored
- Captured photo reflects mirror setting
FR-503: Skin Smoothing (Premium)
- Priority: P2 (Medium)
- Description: Real-time subtle skin smoothing filter
- Acceptance Criteria:
- Premium feature with appropriate gating
- Toggle in settings
- Subtle, natural-looking effect
- Applied to both preview and captured photo
FR-504: Center Stage (Premium)
- Priority: P3 (Low)
- Description: Automatic subject tracking/centering
- Acceptance Criteria:
- Premium feature with appropriate gating
- Uses Apple's Center Stage API if available
- Graceful fallback on unsupported devices
FR-600: Photo Quality Options
FR-601: HDR Mode (Premium)
- Priority: P2 (Medium)
- Description: High Dynamic Range photo capture
- Modes:
- Off
- On
- Auto
- Acceptance Criteria:
- Premium feature with appropriate gating
- HDR indicator in UI when enabled
- Uses system HDR capture capabilities
FR-602: Photo Quality Settings (Premium)
- Priority: P2 (Medium)
- Description: Resolution/quality selection
- Options:
- Medium (Free)
- High (Premium)
- Acceptance Criteria:
- Premium feature for High quality
- Clear indication of current quality setting
- Maximum resolution output for High setting
FR-700: Settings & Synchronization
FR-701: iCloud Sync
- Priority: P1 (High)
- Description: Automatic settings synchronization across devices
- Acceptance Criteria:
- Available to all users (free and premium)
- Real-time sync status with last sync timestamp
- Manual "Sync Now" option
- Uses Bedrock's CloudSyncManager
FR-702: Settings Persistence
- Priority: P0 (Critical)
- Description: All user preferences stored in SyncedSettings model
- Settings Include:
- Ring light: size, color ID, custom color RGB, opacity, enabled
- Camera: position, flash mode, HDR mode, photo quality
- Display: mirror flip, skin smoothing, grid visible
- Capture: timer, capture mode, auto-save
- Premium features: flash sync, center stage
- Acceptance Criteria:
- Settings persist across app launches
- Debounced saves for slider values
- Settings sync via iCloud
FR-800: Branding & Launch Experience
FR-801: Animated Launch Screen
- Priority: P2 (Medium)
- Description: Beautiful branded launch experience
- Acceptance Criteria:
- Animated launch with configurable duration
- Customizable colors, patterns, and layout
- Seamless transition to main app
- Uses Bedrock's LaunchScreenConfig
FR-802: App Icon
- Priority: P2 (Medium)
- Description: Consistent branded app icon
- Acceptance Criteria:
- Generated via Bedrock icon system
- Matches launch screen branding
- Icon generator available in DEBUG builds
FR-900: Premium & Monetization
FR-901: Freemium Model
- Priority: P0 (Critical)
- Description: Free tier with optional Pro subscription
- Free Features:
- Basic ring light (2 colors)
- Photo capture
- 3-second timer
- Grid overlay
- Zoom
- iCloud sync
- Premium Features:
- Full color palette + custom colors
- HDR mode
- High quality photos
- Flash sync
- True mirror mode
- Skin smoothing
- Center stage
- Extended timers (5s, 10s)
FR-902: RevenueCat Integration
- Priority: P0 (Critical)
- Description: Subscription management via RevenueCat
- Acceptance Criteria:
- PremiumManager wraps RevenueCat SDK
- PremiumGate utility for consistent feature gating
- Entitlement named
pro - Settings automatically fall back to free defaults when not premium
FR-903: Paywall
- Priority: P1 (High)
- Description: Pro subscription purchase flow
- Acceptance Criteria:
- Clear presentation of premium features
- Monthly and yearly subscription options
- Restore purchases functionality
- Accessible and localized
FR-904: Debug Premium Mode
- Priority: P3 (Low)
- Description: Testing premium features without subscription
- Acceptance Criteria:
- Environment variable
ENABLE_DEBUG_PREMIUM=1 - Only works in DEBUG builds
- Unlocks all premium features for testing
- Environment variable
Non-Functional Requirements
NFR-100: Accessibility
NFR-101: VoiceOver Support
- Priority: P0 (Critical)
- Acceptance Criteria:
- All interactive elements have meaningful
.accessibilityLabel() - Dynamic state uses
.accessibilityValue() - Actions described with
.accessibilityHint() - Appropriate traits via
.accessibilityAddTraits() - Decorative elements hidden with
.accessibilityHidden(true) - Important events trigger accessibility announcements
- All interactive elements have meaningful
NFR-102: Dynamic Type
- Priority: P0 (Critical)
- Acceptance Criteria:
- All text supports Dynamic Type
- Custom dimensions use
@ScaledMetric - UI remains usable at largest text sizes
NFR-200: Performance
NFR-201: Camera Performance
- Priority: P0 (Critical)
- Acceptance Criteria:
- Smooth, real-time camera preview (30+ fps)
- Minimal latency on capture
- No UI blocking during photo processing
NFR-202: Battery Efficiency
- Priority: P1 (High)
- Acceptance Criteria:
- Efficient camera usage
- Debounced saves reduce iCloud writes
- Screen dimming prevention is intentional (user is actively using camera)
NFR-300: Privacy & Security
NFR-301: Data Collection
- Priority: P0 (Critical)
- Acceptance Criteria:
- No data collection
- No analytics
- No tracking
- Privacy policy reflects minimal data usage
NFR-302: API Key Security
- Priority: P0 (Critical)
- Acceptance Criteria:
- API keys stored in
.xcconfigfiles Secrets.xcconfigis gitignored- Template file provided for setup
- API keys stored in
NFR-400: Localization
NFR-401: String Catalogs
- Priority: P1 (High)
- Acceptance Criteria:
- Uses
.xcstringsfiles for localization - All user-facing strings in String Catalog
- Minimum supported languages: English (en), Spanish-Mexico (es-MX), French-Canada (fr-CA)
- Uses
Project Structure
SelfieCam/
├── App/ # App entry point with launch screen
├── Configuration/ # xcconfig files (API keys)
├── Features/
│ ├── Camera/ # Main camera UI
│ │ ├── ContentView.swift # Main screen coordinator
│ │ ├── Views/ # Camera UI components
│ │ │ ├── CustomCameraScreen.swift
│ │ │ ├── RingLightOverlay.swift
│ │ │ ├── CaptureButton.swift
│ │ │ ├── ExpandableControlsPanel.swift
│ │ │ ├── CaptureEventInteraction.swift
│ │ │ └── ...
│ │ ├── GridOverlay.swift
│ │ └── PostCapturePreviewView.swift
│ ├── Paywall/ # Pro subscription flow
│ │ └── ProPaywallView.swift
│ └── Settings/ # Configuration screens
│ ├── SettingsView.swift
│ ├── SettingsViewModel.swift
│ └── ...
├── Shared/
│ ├── BrandingConfig.swift # App icon & launch screen config
│ ├── DesignConstants.swift # Design tokens (uses Bedrock)
│ ├── Color+Extensions.swift # Ring light color presets
│ ├── Models/ # Data models
│ │ ├── CameraFlashMode.swift
│ │ ├── CameraHDRMode.swift
│ │ ├── PhotoQuality.swift
│ │ └── ...
│ ├── Protocols/ # Shared protocols
│ │ ├── RingLightConfigurable.swift
│ │ ├── CaptureControlling.swift
│ │ ├── CaptureEventHandling.swift
│ │ └── PremiumManaging.swift
│ ├── Premium/ # Subscription management
│ │ └── PremiumManager.swift
│ ├── Services/ # App services
│ │ └── PhotoLibraryService.swift
│ └── Storage/ # Persistence
│ └── SyncedSettings.swift
└── Resources/ # Assets, localization
├── Assets.xcassets/
│ ├── AppIcon.appiconset/
│ ├── LaunchBackground.colorset/
│ └── ...
└── Localizable.xcstrings
Dependencies
| Dependency | Purpose | Integration |
|---|---|---|
| Bedrock | Design system, branding, cloud sync | Local Swift package |
| MijickCamera | Camera capture and preview | SPM dependency |
| RevenueCat | Subscription management | SPM dependency |
Premium Feature Gating Pattern
All premium features use centralized PremiumGate utility:
// Getter pattern - returns free default if not premium
var isMirrorFlipped: Bool {
get { PremiumGate.get(cloudSync.data.isMirrorFlipped, default: false, isPremium: isPremiumUnlocked) }
set {
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
updateSettings { $0.isMirrorFlipped = newValue }
}
}
Premium Feature Matrix
| Feature | Free Value | Premium Value |
|---|---|---|
| Ring light colors | Pure White, Warm Cream | All presets + custom |
| Timer options | Off, 3s | Off, 3s, 5s, 10s |
| Photo quality | Medium | Medium, High |
| HDR mode | Off | Off, On, Auto |
| True mirror | Off | Configurable |
| Skin smoothing | Off | Configurable |
| Flash sync | Off | Configurable |
| Center stage | Off | Configurable |
Known Limitations
Camera Control Button Light Press
Status: Not Working - Needs Investigation
The Camera Control button (iPhone 16+) full press works for photo capture, but the light press (secondary action) does not work.
What Works:
- Camera Control full press → triggers photo capture
- Volume up/down → triggers capture
What Doesn't Work:
- Camera Control light press → no event received
- Camera Control swipe gestures (zoom) → Apple-exclusive API
Possible Causes:
- Light press may be restricted to first-party apps
- MijickCamera session may interfere with light press detection
- Accessibility settings may need explicit enablement
User Workaround: Check Settings > Accessibility > Camera Control:
- Ensure Camera Control is enabled
- Ensure Light-Press is turned ON
- Adjust Light-Press Force if needed
Future Enhancements
Potential areas for expansion:
- Real-time filters (beauty, color grading)
- Gesture-based capture (smile detection)
- Widget for quick camera access
- Apple Watch remote trigger
- Export presets (aspect ratios, watermarks)
- Social sharing integrations
- Camera Control button swipe-to-zoom (if Apple makes API public)
Required Permissions
| Permission | Reason |
|---|---|
| Camera | Photo preview and capture |
| Photo Library | Save captured photos |
| Microphone | May be requested by camera framework (not actively used) |
| iCloud | Settings synchronization (optional) |
Development Setup
1. Clone and Configure
git clone https://github.com/yourusername/SelfieCam.git
cd SelfieCam
cp SelfieCam/Configuration/Secrets.xcconfig.template SelfieCam/Configuration/Secrets.xcconfig
2. Add API Key
Edit Secrets.xcconfig:
REVENUECAT_API_KEY = appl_your_actual_api_key_here
3. RevenueCat Setup
- Create RevenueCat account and project
- Connect to App Store Connect
- Create products and entitlement named
pro - Copy Public App-Specific API Key to
Secrets.xcconfig
4. Test Premium Features
Set environment variable in scheme:
- Name:
ENABLE_DEBUG_PREMIUM - Value:
1
Code Quality Standards
- No magic numbers: All values from Design constants
- Full accessibility: Every interactive element has VoiceOver support
- Protocol-first: Shared behavior defined via protocols
- Separation of concerns: Views are dumb, ViewModels contain logic
- Modern APIs: Swift 6, async/await, @Observable
- Documentation: Code comments, README, PRD
This PRD serves as the primary requirements document for SelfieCam development.