Native Mobile Interface
This section covers the native Capacitor features that make DreamStream feel like a true native app, not just a web wrapper.
At a glance
| Feature | Purpose | Web | Native |
|---|---|---|---|
| Authentication | Google, Apple, Magic Link, Email/Password | โ OAuth | โ Native |
| App Shortcuts | Long-press icon โ "Record Dream" | โ | โ |
| Siri Shortcuts | Voice command: "Hey Siri, record dream" | โ | โ ๏ธ Deprecated |
| Haptic Feedback | Tactile response on key actions | โ | โ |
| Biometric Lock | Face ID / Fingerprint to unlock app | โ | โ |
| Pull-to-Refresh | Native-feel refresh on journal | Degraded | โ |
| Network Detection | Offline banner + auto-recovery | โ | โ |
| Native Camera | Photo picker for Digital Twin | โ | โ |
| Native Share | Share images to other apps | โ | โ |
| InโApp Review Prompt | Native App Store rating sheet (requested at delight moments) | โ | โ iOS |
| OTA Updates | Silent app updates via Capgo | โ | โ |
1) Authentication
DreamStream supports multiple authentication methods, with behavior that varies by platform.
Available Methods
| Method | Web | Android | iOS |
|---|---|---|---|
| OAuth redirect | OAuth (in-app browser) | OAuth (in-app browser) | |
| Apple | OAuth redirect | OAuth redirect | Native FaceID/TouchID |
| Magic Link | โ Email link | โ Email link | โ Email link |
| Email/Password | โ | โ | โ |
Native Apple Sign-In (iOS Only)
On iOS devices, Apple Sign-In uses the native authentication sheet instead of a web redirect. This provides:
- FaceID/TouchID authentication (same as App Store purchases)
- No browser popup or redirect
- Faster, more seamless experience
First-login name capture
Apple only sends the user's full name on the first sign-in. DreamStream automatically captures and saves this to user metadata. Subsequent logins return null for name fields.
Hide My Email (Apple)
Apple users can choose to hide their email address during sign-up. When this happens:
- Apple generates a proxy email (e.g.,
xyz123@privaterelay.appleid.com) - This email forwards to the user's real address
- DreamStream allows these users to authenticate normally
Platform Behavior
flowchart TD
A[User taps Sign In] --> B{Platform?}
B -->|iOS + Apple| C[Native FaceID/TouchID sheet]
B -->|Web/Android + Apple| D[OAuth browser redirect]
B -->|All + Google| E[OAuth browser redirect]
C --> F[Identity token โ Supabase]
D --> F
E --> F
F --> G[User authenticated]
Implementation
Technical: Code locations
- Native Apple Sign-In:
src/services/nativeService.tsโsignInWithApple() - Auth UI component:
src/components/Auth.tsxโhandleSocialLogin() - Supabase client:
src/lib/supabase.ts
2) App Shortcuts (Long-Press Launcher Icon)
What users see
When users long-press the DreamStream app icon, they see a quick action:
- "Record Dream" โ Tapping this opens the app directly into Quick Capture recording mode
Behavior
- The shortcut dispatches a
shortcut:recordevent - The app listens for this event and opens the Quick Capture overlay with recording auto-started
- Works on both Android and iOS
Deep link support
The app also responds to a deep link that triggers the same Quick Capture flow (examples: dreamstream://record or dreamstream://shortcut/record).
flowchart TD
A[Long-press app icon] --> B[Tap 'Record Dream']
B --> C[App opens with Quick Capture overlay]
C --> D[Recording starts automatically]
3) Siri Shortcuts (iOS Only)
Deprecated
Siri Shortcuts support is currently disabled due to plugin incompatibility with newer Capacitor/iOS tooling. Users can use the App Shortcut (โRecord Dreamโ) instead.
Siri voice phrases like โHey Siri, record dreamโ are not currently supported in production builds. If this is re-enabled in the future, it should launch the same Quick Capture experience as the app shortcut.
Technical: Siri Setup
Historical notes may exist in docs/NATIVE_SIRI_SETUP.md, but the current app does not rely on this path in production.
4) Haptic Feedback
DreamStream uses haptics to create a premium tactile experience.
Where haptics are used
| Action | Haptic Type | Location |
|---|---|---|
| Dream saved successfully | Success notification | Save button |
| Save failed | Error notification | Save button |
| Share button tapped | Light impact | Dream Detail |
| Streak milestone reached | Strong notification | Celebration modal |
| Pull-to-refresh threshold | Selection | Journal scroll |
| Pull-to-refresh complete | Medium impact | Journal scroll |
| Tab navigation | Light impact | Bottom nav |
| Create button | Medium impact | Bottom nav |
Why it matters
Haptics differentiate DreamStream from web apps. Users subconsciously feel the app is "real" because their device responds physically to interactions.
5) Biometric Lock (Face ID / Fingerprint)
What users see
In Settings โ Preferences, users can toggle:
- Biometric Lock โ When enabled, the app requires Face ID or fingerprint to unlock
When biometric prompt appears
- When the app returns from background (user switches back to DreamStream)
- On app cold start if the setting is enabled
What happens if authentication fails
- The user stays on a locked screen
- They can retry authentication
- The app does not unlock without successful biometrics
Device storage
Device-only setting
The biometric lock preference is stored on-device only (not synced to cloud). If a user switches devices, they'll need to re-enable this setting.
- Key:
localStorage['biometric_lock_enabled']
6) Pull-to-Refresh
What users see
On the Dream Journal and Home Dashboard, users can pull down to refresh content.
Behavior
- A haptic "selection" fires when crossing the refresh threshold
- A spinner appears during the refresh
- A haptic "medium impact" fires on completion
- Smooth spring animations throughout
Implementation
- Uses a custom
PullToRefreshcomponent with GPU-accelerated transforms - Respects
touch-action: pan-yfor native-like scroll behavior - Many screens also use โnative-feelโ scroll containers for iOS momentum scrolling.
Native-feel scrolling (momentum + overscroll)
DreamStream uses CSS utilities (see src/index.css) for scroll containers that should feel native on iOS:
.native-scroll: vertical momentum scrolling via-webkit-overflow-scrolling: touch.native-scroll-contained: same, plusoverscroll-behavior: containto prevent scroll chaining (useful for modals/nested lists).native-scroll-x: horizontal scroll areas (carousels/tabs) with gesture-friendlytouch-action
These utilities should be applied to containers with a constrained height (e.g., Settings, modals, tab panels). iOS โrubber-bandโ/elastic overscroll still appears when the container hits its edge; containment prevents accidentally scrolling the background.
7) Network Detection & Offline Banner
What users see
When the device loses connectivity:
- An Offline Banner appears at the top of the screen
- The banner reads: "You're offline. Some features may be limited."
- When connectivity returns, the banner disappears automatically
Graceful degradation
- Dreams and quick-capture drafts that fail cloud save due to connectivity are placed in the Offline Queue (see Capture & Offline Sync)
- Cached dream and profile data remain accessible
- AI generation and chat require connectivity
8) Native Camera Picker
Where it's used
- Digital Twin photo capture (Settings โ Dream Persona)
- Known People reference photos (Settings โ Dream Persona)
What users see
When tapping to add/change a photo, the native action sheet appears:
- Take Photo โ Opens device camera
- From Gallery โ Opens photo library
- Cancel โ Dismisses without action
This is a native picker, not a web file input.
9) Native Share
What users can share
From Dream Detail, users can share:
- Dream Image โ The main AI visualization
- Comic โ The 9-panel comic
- Insight Lens โ The decoded/annotated image
What users see
Tapping the share button opens the native share sheet, allowing sharing to any app (Messages, Instagram, Save to Files, etc.).
10) InโApp Review Prompt (iOS Only)
What users see
DreamStream may occasionally request the native iOS rating/review sheet.
Important: iOS may choose not to display it even when requested.
When we request it
We only request a review after โdelightโ moments (not during onboarding), such as:
- After a user has logged multiple dreams
- After a share/download action
- After a streak milestone
Implementation
Technical: Code locations
- Gating rules:
src/services/ratingPromptService.ts - Request call:
src/services/nativeService.tsโrequestInAppReview() - Trigger points:
App.tsx
11) OTA Updates (Capgo)
What happens (invisible to users)
DreamStream uses Capgo for over-the-air updates:
- On app launch, the app checks for updates
- If an update is available, it downloads in the background
- On next app restart, the update is applied seamlessly
- Users never need to visit the App Store for non-native updates
User-visible behavior
- Updates happen silently
- The app may show a brief "Updating..." message in rare cases
12) Status Bar & Screen Orientation
Status bar
- Matches app theme automatically (light text on dark background)
- Hides during fullscreen lightbox viewing
- Returns when lightbox closes
Screen orientation
- App is portrait-locked by default
- Lightbox allows landscape rotation for viewing images
- When lightbox closes, app returns to portrait
13) In-App Browser
Where it's used
- Legal links (Terms of Service, Privacy Policy)
- Help links (if applicable)
What users see
External links open in an in-app browser modal instead of kicking users to Safari/Chrome. This keeps users in the DreamStream experience.
14) Text-to-Speech (Read Aloud)
Where it's used
- Dream Insights โ Tap "Read Aloud" to hear analysis spoken
- IRT Wizard โ Rescripted endings can be read aloud for rehearsal
Behavior
- Uses native TTS engine on device
- On web, falls back to Web Speech API
- Tapping again stops playback
See also: Chat & Audio Experiences for Read Aloud details.
15) Offline Caching
Text data cache
When online, DreamStream caches:
- Dreams list
- User profile
On subsequent app opens, the cached data loads instantly while fresh data fetches in background.
Image cache
- Dream images are cached to device storage (native only) for faster reloads
- Images older than 7 days are automatically cleared on app startup
- Cache is cleared on logout to prevent cross-user data leakage on shared devices
- If an image is not cached and the device is offline, a placeholder appears
Implementation map (for accuracy checks)
Component files
- Native service wrapper:
src/services/nativeService.ts - Shortcut configuration:
nativeService.configureShortcuts() - Biometric auth:
nativeService.authenticate() - Pull-to-refresh:
components/PullToRefresh.tsx - Offline banner:
components/OfflineBanner.tsx - Network context:
src/contexts/NetworkStatusContext.tsx - Lightbox orientation:
components/Lightbox.tsx